欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java多线程机制

程序员文章站 2022-10-24 08:53:14
//操作系统可以产生多个进程,每个进程也可以产生多个线程 1.线程 //"主线程”是main线程 //线程有4种状态:新建、运行、中断、死亡 (1)新建: ①通过继承Thread类创建: 需要重写Thread类的run()方法; //优点:可以在子类中增加新的成员变量和方法,使线程具有某种属性和功能 ......

//操作系统可以产生多个进程,每个进程也可以产生多个线程

1.线程

//"主线程”是main线程

//线程有4种状态:新建、运行、中断、死亡

(1)新建:

①通过继承Thread类创建:

需要重写Thread类的run()方法;

//优点:可以在子类中增加新的成员变量和方法,使线程具有某种属性和功能。

  缺点:Java不支持多继承,Thread类的子类不能再扩展其他的类。

 

②通过实现Runnable接口创建:

构造方法:Thread(Runnable target)

//优点:对于使用同一目标对象的线程,目标对象的成员变量是这些线程共享的数据单元;

     创建目标对象的类在必要时可以是某个特定类的子类。

因此使用Runnable接口比使用Thread的子类更具有灵活性。

 

 

中断原因:

①JVM将CPU资源从当前线程切换给其他线程,使本线程让出CPU的使用权处于中断状态。

②线程使用CPU资源期间,执行了sleep(int millsecond)方法,使当前线程进入休眠状态。

③线程使用CPU资源期间,执行了wait()方法,使得当前线程进入等待状态。

④线程使用CPU资源期间,执行某个操作进入阻塞状态,比如执行读/写操作引起阻塞。

 

死亡(线程释放了实体和线程对象的内存)原因:

①执行完run()方法中的全部语句,结束了run()方法。

②线程被提前强制性地终止,即强制run()方法结束。

 

目标对象与线程的关系:

①完全解耦:目标对象没有组合线程对象。

②弱耦合:目标对象可以组合线程,即将线程作为自己的成员(在Thread子类或实现Runnable的类中创建线程)。

//在实际问题中,根据实际情况确定目标对象和线程是组合或完全解耦关系,两种关系各有优缺点。

 

线程的常用方法:

1.start() throws IllegalThreadStateException

启动线程,二次调用start()方法会导致异常;

2.run()

定义线程对象被调度之后所执行的操作,系统自动调用而用户程序不得引用;

3.sleep(int millsecond) throws InterruptedException

参数millsecond是以毫秒为单位的休眠时间,如果线程在休眠时被打断,JVM就抛出异常;

4.isAlive()

判断线程是否存在(非新建和死亡状态);

5.currentThread()

返回当前正在使用CPU资源的线程;

6.interrupt()

"吵醒"休眠的线程,导致休眠的线程发生InterruptedException异常;

7.setPriority(int grade) throws IllegalArgumenException

调整线程的优先级,参数grade参数为1~10之间,若不在该范围则发生异常(注意有些os只识别3个级别:1、5和10);

//实际编程中,不提倡使用线程的优先级来保证算法的正确执行

 

2.线程同步(用synchronized修饰)

线程同步机制:当一个线程A使用synchronized方法时,其他线程想使用这个synchronized方法时就必须等待,直到线程A使用完该synchronized方法。

同步方法中的方法(都是Object类的final方法):

1.wait()

中断线程的执行,使本线程等待,暂时让出CPU的使用权;

2.notify()

通知处于等待中的某一个线程结束等待;

3.notifyAll()

通知所有由于使用这个同步方法而处于等待的线程结束等待,曾中断的线程从刚才的中断处继续执行这个同步方法;

//不可以在非同步方法中使用上述的三个方法

//遵循"先中断先继续”的原则

 

3.线程联合

一个线程A在占有CPU资源期间,可以让其他线程调用join()方法和本线程联合,如:B.join();

如果线程A在占有CPU资源期间一旦联合B线程,那么A线程将立刻中断执行,一直等到它联合的B线程执行完毕,A线程再重新排队等待CPU资源,以便恢复执行。

//如果A准备联合的B线程已经结束,那么B.join()不会产生任何效果。

 

4.GUI线程

当Java程序包含GUI时,JVM在运行程序时会自动启动更多的线程,其中两个重要的线程:AWT-EventQuecue和AWT-Windows

当触发ActionEvent事件时,AWT-EventQuecue线程就立刻等候执行处理事件的代码。

 

5.计时器线程

javax.swing.Timer类(避免与java.util.Timer类混淆):

构造方法:

Timer(int a)

必须调用addActionListener(ActionListener listener)方法获得监视器(必须是组件类);

Timer(int a,Object b)

参数a的单位是毫秒,确定计时器每隔a毫秒"振铃"一次,参数b是计时器的监视器;

 

常用方法:

1.setReapeats(boolean b)

只想计时器振铃一次,可以调用此方法,参数b取值false;

2.setInitialDelay(int depay)

设置首次振铃的延时,默认延时为a;

3.start()

启动计时器;

4.stop()

停止计时器,即挂起线程;

5.restart()

重新启动计时器,即恢复线程;

 

6.守护线程

线程默认是非守护线程(用户线程),一个线程调用void setDaemon(boolean on)方法将自己设置成一个守护线程,如:thread.setDaemon(true);

当所有用户线程结束运行时, 即使守护线程的run方法还未执行完,也立刻结束运行。

//守护线程用来做一些不是很严格的工作