Java多线程之线程的控制

时间:2022-03-30 05:59:02

Java多线程之线程的控制



  • 线程中的7 种非常重要的状态: 

初始New、可运行Runnable、运行Running、阻塞Blocked、锁池lock_pool、等待队列wait_pool、结束Dead

如果将“锁池”和“等待队列”都看成是“阻塞”状态的特殊情况,那么可以将线程归纳为5个状态:

新建,就绪,运行,阻塞,死亡。

                                        

                 ┌--------------------< 阻塞

                 ↓                    (1)(2)(3)        结束

                ①②③        OS调度         ↑             ↑

    初始-------> 可运行 ↹---------------↹ 运行 >-----------┤

    t.start()启动 ↑                        ↓              ↓o.wait()

                 └-----< 锁池 ←---------<┘←-------< 等待队列

                  获得锁标志   synchronized(o)

注意:图中标记依次为

    ①输入完毕;    ②wake up    ③t1 退出

    ⑴等待输入(输入设备进行处理,而CUP 不处理),则放入阻塞,直到输入完毕。

    ⑵线程休眠sleep()

    ⑶t1.join()将t1 加入运行队列,直到t1 退出,当前线程才继续。

        特别注意:①②③与⑴⑵⑶是一一对应的。

    进程的休眠:Thread.sleep(1000);//括号中以毫秒为单位

    当线程运行完毕,即使在结束时时间片还没有用完,CPU 也放弃此时间片,继续运行其他程序。

    T1.join 实际上是把并发的线程编成并行运行。



Java多线程之线程的控制



  •    实现对多线程的控制:

控制多线程,记住下面几个API就够了:

   1,start方法:创建一个线程。值得注意的是,new一个线程的时候,只是表示该线程处于新建状态,并不是执行状态。使用start方法后启动一个线程,线程处于就绪状态,也并不是说直接就在运行了,它表示这个线程可以运行了,但是什么时候开始运行,取决于JVM里线程调度器的调度。

   2,stop方法:结束一个线程。容易导致死锁,不推荐使用。值得注意的是,不要试图在一个线程已死亡的情况下再次调用start方法来启动该线程,会报illegalThreadStateException错的。

   3,join方法:在一个线程中加入一个线程。当在某个程序执行流中调用了其他线程的join方法时,调用线程将被阻塞,直到被join方法加入的join线程完成为止。

   4,sleep方法:让线程睡觉。使当前正在执行的线程暂停一段时间,并进入阻塞状态。

   5,yield方法:和sleep方法相似,让当前正在执行的线程暂停一下,但是他不会阻塞这个线程,它只是将这个线程转入就绪状态。

   6,setPriority方法:设置线程优先级。set和getPriority设置和获得线程的优先级,1到10一共10个数字,默认是5,数字越大优先级越高,越容易获得执行机会。 为了跨平台,最好不要使用优先级决定线程的执行顺序。这个时候使用3个静态常量:max_Priority,min_Priority,norm_Priority。

   7,setDaemon方法:设置后台线程。   Daemon Threads(daemon 线程)是服务线程,当其他线程全部结束,只剩下daemon线程时,虚拟机会立即退出。

    Thread t = new DaemonThread();

    t.setDaemon(true);//setDaemon(true)把线程标志为daemon,其他的都跟一般线程一样

    t.start();//一定要先setDaemon(true),再启动线程

    在daemon线程内启动的线程,都定为daemon线程

    8,wait(),Notify()方法在后面介绍同步锁的时候在仔细说。 在运行状态中,线程调用wait(),表示这线程将释放自己所有的锁标记,同时进入这个对象的等待队列。等待队列的状态也是阻塞状态,只不过线程释放自己的锁标记。用notify()方法叫出之后,紧跟着刚才wait();的位置往下执行。如果一个线程调用对象的notify(),就是通知对象等待队列的一个线程出列。进入锁池。如果使用notifyall()则通知等待队列中所有的线程出列。

  • 有一个问题,在什么情况下,一个线程将进入阻塞状态?

1,线程调用了sleep方法,主动放弃它所占有的处理器资源

2,线程调用了阻塞式IO方法,在方法返回之前,线程阻塞了

3,线程试图获得一个同步监听器,但是该同步监视器正被其他的线程持有

4,线程在等待某一个notify通知

5,线程调用了suspend方法将线程挂起了。





要是让一个线程由阻塞状态变成了就绪状态正好和上面的情况相反,最后一点使用resume方法就好了。值得注意的是:suspend()将运行状态推到阻塞状态(注意不释放锁标记)。恢复状态用resume()。Stop()释放全部。这几个方法上都有Deprecated 标志,说明这个方法不推荐使用。一般来说,主方法main()结束的时候线程结束,可是也可能出现需要中断线程的情况。对于多线程一般每个线程都是一个循环,如果中断线程我们必须想办法使其退出。如果想结束阻塞中的线程(如sleep 或wait),可以由其他线程对其对象调用interrupt()。用于对阻塞(或锁池)会抛出例外Interrupted。