Java之多线程机制-(1)

来源:互联网 发布:2017程序员看的书 编辑:程序博客网 时间:2024/06/05 15:19

主线程(main线程):

当JVM加载代码,发现main方法之后,就会启动一个线程,这个线程称为“主线程”(main线程),该线程负责执行main方法。如果在main方法的执行中再创建线程,就成为程序中的其他线程。如果main方法中没有创建其他的线程,那么当main方法执行完最后一个语句,即main方法返回时,JVM就会结束我们的Java应用程序。如果main方法中又创建了其他线程,那么JVM就要在主线程和其他线程之间轮流切换,保证每个线程都会有机会使用CPU资源,main方法即使执行完最后的语句(主线程结束),JVM也不会结束Java应用程序,JVM一直要等到Java应用程序中的所有线程都结束后,才结束Java应用程序。

线程的状态与生命周期:

新建:当一个thread类被声明并创建时,线程处于新建状态。此时它有了相应的内存空间和其他资源。

运行:线程创建后仅仅是占有了内存资源,在JVM管理的线程中还没有这个线程,此线程必须调用start()方法通知JVM有一个新线程排队等候切换了。当JVM将CPU使用权切换给该线程时,若线程是Thread的子类,该类中的run()方法就立刻执行,run()方法规定了该线程的具体使命。所以程序必须在子类中重写父类的run()方法。(Thread类中的run()方法没有具体内容)。注意在线程没有结束run()方法之前,不要让线程再调用start()方法,否则将发生IllegalThreadStateException异常。

中断:(4种中断原因)

1.线程在使用CPU资源期间,JVM将CPU资源从当前线程切换给其他线程,使本线程让出CPU的使用权而处于中断状态。
2.线程在使用CPU资源期间,执行了sleep(int millsecond)方法,使线程进入睡眠状态,退出线程队列经过参数millsecond指定的毫秒数之后,该线程就重新进入线程队列中等待CPU资源。
3.线程在使用CPU资源期间,执行了wait()方法,使线程进入等待状态,等待状态的线程不会主动进入到线程列队中,必须由其他线程调用notify()方法通知它,使得它重新进到线程队列中。
4.线程在使用CPU资源期间,执行某个操作进入阻塞状态。阻塞状态下线程不能进入线程队列。

死亡:(释放分配给线程对象的内存)

1.执行完run()方法中的全部语句,线程则死亡。
2.线程被提前强制性终止,即强制run()方法结束。

Thread类与线程的建立:

使用Thread的子类:需重写父类的run()方法

使用Thread类:

Thread类的构造方法:Thread(Runnable target)
Runnable是一个接口,该接口中有一个run()方法,示例如下:
class showTarget implements Runnable{   //用showTarget类来实现Runable接口public void run(){                  //重写接口的方法for(int i=1; i<=5; i++)System.out.println("hello world!");}}public class E{public static void main(String args[]){showTarget show_Interface = new showTarget();Thread show = new Thread(show_Interface);  //创建show线程,show_Interface称为线程show的目标对象show.start();   //启动线程for(int i=1; i<=5; i++)System.out.println("thank you!!");}}</span>
注意:线程调用start()后,并不一定执行该线程,只是将该线程加入到JVM的线程队列中。只有当它享用CPU资源时,目标对象就会自动调用接口中的run()方法(接口回调),这一过程是自动实现的。

目标对象和线程的关系:

1.目标对象和线程完全解耦(目标对象不含线程对象的引用),这种情况下,目标对象经常需要通过获得线程的名字来确定是哪个线程正在占有CPU资源

class House implements Runnable{  //实现Runnable的类中不包含线程对象int waterAmout;public void setWater(int n){waterAmout = n;}public void run(){String name = Thread.currentThread().getName(); //需要获得正在执行的线程名字while(true){if(name.equals("狗")){waterAmout -= 2;System.out.println(name+"喝水");}if(name.equals("猫")){waterAmout -= 1;System.out.println(name+"喝水");}System.out.println("剩"+waterAmout);try{Thread.sleep(2000);}catch(InterruptedException e){}if(waterAmout<0)return;}}}public class E{public static void main(String args[]){House house = new House();house.setWater(10);Thread dog = new Thread(house);  //使用相同的目标对象,那么waterAmout是两个线程的共享数据Thread cat = new Thread(house);dog.setName("狗");cat.setName("猫");dog.start();cat.start();}}

2.目标对象组合线程(即目标对象将线程作为自己的成员)(弱耦合)

class House implements Runnable{ int waterAmout;Thread dog, cat;                                //线程作为目标对象的成员House(){dog = new Thread(this);cat = new Thread(this);}public void setWater(int n){waterAmout = n;}public void run(){Thread currentThread = Thread.currentThread();while(true){if(currentThread==dog){waterAmout -= 2;System.out.println("狗喝水");}if(currentThread==cat){waterAmout -= 1;System.out.println("猫喝水");}System.out.println("剩"+waterAmout);try{Thread.sleep(2000);}catch(InterruptedException e){}if(waterAmout<0)return;}}}public class E{public static void main(String args[]){House house = new House();house.setWater(10);house.dog.start();house.cat.start();}}

线程的常用方法:

1.start(),使线程从新建状态进入就绪队列排队,只有处于新建状态的线程才可以调用start()方法。
2.run(), 定义线程对象被调度之后做执行的操作,是系统自动调用而用户程序不得引用的方法。
3.sleep(int millsecond)., 当优先级高的线程需要优先级低的线程完成一些工作时,优先级高的方法可以再它的run()方法中调用sleep方法来使自己放弃CPU资源。如果线程在休眠时被打断,JVM就抛出InterruptedException异常,因此,必须在try-catch语句中调用sleep方法。
4.isAlive(), 在线程的start()方法运行到run()方法结束之前,调用isAlive()方法返回true。
5.currentThread(), 类方法,返回当前正在使用cpu资源的线程。
6.interrupt(), 当一些线程调用sleep方法出于休眠状态时,一个占有CPU资源的线程可以让休眠的线程调用interrupt方法‘吵醒’自己,即导致休眠的线程发生InterruptedException异常,从而结束休眠,重新排队等候CPU资源。例子如下:
class classRoom implements Runnable{Thread student, teacher;classRoom(){teacher = new Thread(this);student = new Thread(this);teacher.setName("王教授");student.setName("张三");}public void run(){if(Thread.currentThread()==student){try{System.out.println(student.getName()+"正在睡觉,不听课");Thread.sleep(60*60*1000);   //sleep后下面语句不执行}catch(InterruptedException e){System.out.println(student.getName()+"被老师叫醒了");}System.out.println(student.getName()+"开始听课");}else{for(int i=0; i<3; i++){System.out.println("上课!");try{Thread.sleep(500);}catch(InterruptedException e){}}student.interrupt();   //打断Student睡眠,使其执行异常函数,继而执行后面语句}}}public class E{public static void main(String args[]){classRoom room = new classRoom();room.student.start();room.teacher.start();}}


0 0