java的多线程
进程:程序的执行过程,持有内存资源
线程:是系统的最小执行单元,共享进程的资源
线程之间可以互斥、也可以同步;
Thraed类:
通过一个案例来了解线程Thread类和Runnable接口的运用:
案例须知:
1、实现舞台线程(继承Thread类)
2、实现军队线程,通过调用军队线程实现农民和政府双军队线程,将军队交战线程放到舞台线程中开始运行,双线程是交叉运行;(继承Runnable接口)
3、实现一个英雄进场线程(继承Thread类),在双线程结束后将英雄入场线程放到舞台线程中运行,运行后结束后舞台线程随之结束;
军队线程:
package com.thread; public class Army implements Runnable { volatile boolean keepRunning =true;//保证了线程可以读取其他线写入的值 @Override public void run() { // TODO Auto-generated method stub while(keepRunning) { for(int i = 0;i<5;i++) { System.out.println(Thread.currentThread().getName()+"进攻对方["+i+"]次"); Thread.yield();//让出处理器时间,下次进攻是谁还不一定呢 } } System.out.println(Thread.currentThread().getName()+"结束了战斗"); } }
英雄进场线程:
package com.thread; public class Hero extends Thread { public void run() { System.out.println(Thread.currentThread().getName()+"加入了战斗"); for(int i = 0;i<10;i++) { System.out.println(Thread.currentThread().getName()+"释放技能:“捞人自捞”"); } System.out.println(Thread.currentThread().getName()+"结束了战斗"); } }
舞台线程:
package com.thread; public class Stage extends Thread { public void run() { Army armyOfZf = new Army(); Army armyOfNm = new Army(); Thread armyOfZfTh = new Thread(armyOfZf,"政府"); Thread armyOfNmTh = new Thread(armyOfNm,"农民"); armyOfNmTh.start(); armyOfZfTh.start(); try { Thread.sleep(50); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } armyOfZf.keepRunning = false; armyOfNm.keepRunning = false; Thread mrya = new Hero(); mrya.setName("余桉"); System.out.println("农民和政府打的不可开交时"+mrya.getName()+"冲入了战场!!!"); try { Thread.sleep(50); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } mrya.start(); try { mrya.join();//等待mrya线程运行完后,程序才会继续执行; } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } try { armyOfNmTh.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args) { // TODO Auto-generated method stub Stage test = new Stage(); test.start(); } }
注意:这里的案例我们停止线程是用了一个一个布尔值keepRunning,将改变其值使得线程运行完毕,而java本身的Thread类有提供一个stop()的线程停止方法,但这个方法是不正确的停止方法,因为这个是“猝死”类型的停止方法,会让线程直接停止,这样会使得我们没法输出提示信息,也没能有效地处理线程的后=后续清理工作;因此说这个方法是不正确的停止方法;
两个线程发生争用条件:两个不同的线程同时访问同一资源,在线程一把原本的资源改了,但是资源并没来得及传入硬盘而是只存在于内存中,此时若是切换到线程2.线程二对该资源操作完成后又切换到线程一,线程一继续刚没结束的上下文,把刚修改存在内存中的资源一再返回硬盘中,此时就会使得线程二对于资源的操作修改被覆盖,导致资源的状态和我们想要的不一样;
线程互斥和同步:互斥即对线程进行加锁,需等线程解锁后别的线程才可以操作该共享对象;同步是指线程对共享对象的使用,需要让其共享资源满足于什么条件下才可以使用,此时线程会调用wait()方法进入等待,等别的线程操作完共享对象,达到该条件后再触发notifyAll(),唤醒等待状态的所有线程;
先创建一个共享对象:
线程开始之前:
通过synchronized关键字定义临界端,wait()使得线程进入等待阶段,在Wait set集合中进行等待,别的线程可以进入这个临界端,当运行notifyAll()时唤醒所有线程;