接着来讨论java中多线程问题。


先说一个问题:  现在有两个线程,怎么样才能让一个线程执行结束之后再执行另一个线程。

其实只要讲要先执行的线程设置为加入线程就行了。-->join()


这里写一下怎么来实现

假如现在有两个线程m1和m2,现在要让m1先执行,也就是讲m1设置为加入线程。要抓一个异常。

try {
mt1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

关于线程死亡:

   public final void stop():直接杀死

   public void interrupt():直接杀死,在死前,还可以有遗言

来说一下俩者的区别:

stop是直接将线程杀死

interrupt:线程再被杀死后,会把后边的代码执行完,然后再死亡,就是我们说的留遗言。


线程的生命周期(画图讲解),面试题

1.新建

2.就绪

3.运行

4.有可能阻塞

5.死亡



多线程(二)_第1张图片

生命周期图解如上图


这里来一个案例   

案例:以给学生设置和获取姓名和年龄为例,演示线程通信问题

  线程间通讯:

  资源:Student

  设置数据线程:SetThread

  获取数据线程:GetThread

  测试类:StudentDemo

  

  问题1:控制台出现的结果是:null---0

  设置和获取线程使用的学生资源不是同一个。

  如何解决这个问题呢?

  把资源作为构造参数传递即可。

  

  问题2:产生了2个问题

  相同的数据出现了多次

  CPU的一点点时间片就足够我们的程序执行很多次

  数据出现了问题(数据安全问题)

  是否是多线程环境

 

  是否有共享数据

 

  是否有多条语句操作共享数据

 

  既然我们知道它是出现了数据安全问题,我们就应该来解决它。

  如何解决呢?加锁

  

  问题3:加了锁以后,数据还是有问题

  多个线程都要加锁

  多个线程加的锁必须是同一把锁


以上问题是这个程序中辉徐导的问题,也是必须要解决的。通过这个案例,我们对多线程应该会有一个更为系统,更为全面的认识。


大家可以自己去实现,代码详见第十六天资料  com.edu_04


关于线程池

程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。

线程池的特点:

线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。

在JDK5之前,我们必须手动实现自己的线程池,从JDK5开始,Java内置支持线程池


线程池的创建机操作

//提交给线程池两个任务,
ExecutorService pool = Executors.newFixedThreadPool(2);
//创建任务
MyRunnbale my1 = new MyRunnbale();
MyRunnbale my2 = new MyRunnbale();
//3.提交任务
pool.submit(my1);
pool.submit(my2);
//关闭线程池
//void shutdown()
pool.shutdown();

另外在run方法中写入要运行的代码就好了。  这里线程池的创建的方法要记住,他不同于new对象,是调一个工厂类方法。


java中多线程方面就已经结束了,来简单总结一下,并说说该注意的。


线程的实现有两种方法,继承Thread类或者实现runnable接口。一般推荐使用实现runnable接口这一种方法,因为他更能体现面向对象的思想,还有一个重要的原因,大家都知道,在java中,支持单继承多实现,如果用第二种方法,还可以继承别的类,实现更多的接口。


多线程中会有线程不安全的问题,在编写代码的时候要注意解决。


要了解线程的生命周期,理解调用start之后,仅仅只是就绪状态,只有在抢到cpu放入时间片的时候,才执行。


线程池里的线程在执行完代码之后并不会死亡,会自己回到线程池中等待下一个线程对象调用,所以,创建一个含有两个线程的线程池,并不是只能以操作两个线程,只要等到一个线程执行完毕,就可以在使用线程池里的线程。