进程与线程
来源:互联网 发布:淘宝地推团队 编辑:程序博客网 时间:2024/05/29 21:33
进程
- 程序(任务)的执行过程 – 动态性
- 持有资源(共享文件,共享内存)和线程–资源的载体
线程
- 线程是系统中最小的执行单元
- 同一进程中有多个线程
- 线程共享进程的资源
线程的交互
互斥&同步
线程示例
package com.h.concurrent;/** * Created by John on 2017/5/13. */public class Actor extends Thread { public void run(){ System.out.println(getName()+"是一个演员!"); int count = 0; boolean keepRunning = true; while(keepRunning){ System.out.println(getName()+"登台演出:"+ (++count)); if(count == 100){ keepRunning = false; } if(count%10== 0){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } System.out.println(getName()+"的演出结束了!"); } public static void main(String[] args){ Thread actor = new Actor(); actor.setName("Mr. Thread"); actor.start(); Thread actressThread = new Thread(new Actress(),"Ms. Runnable"); actressThread.start(); }}class Actress implements Runnable{ public void run() { System.out.println(Thread.currentThread().getName()+"是一个演员!"); int count = 0; boolean keepRunning = true; while(keepRunning){ System.out.println(Thread.currentThread().getName()+"登台演出:"+ (++count)); if(count == 100){ keepRunning = false; } if(count%10== 0){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } System.out.println(Thread.currentThread().getName()+"的演出结束了!"); }}
隋唐演义大舞台
package com.h.concurrent;//军队线程//模拟作战双方的行为public class ArmyRunnable implements Runnable { //volatile保证了线程可以正确的读取其他线程写入的值 //可见性 ref JMM, happens-before原则 volatile boolean keepRunning = true; public void run() { while(keepRunning){ //发动5连击 for(int i=0;i<5;i++){ System.out.println(Thread.currentThread().getName()+"进攻对方["+i+"]"); //让出了处理器时间,下次该谁进攻还不一定呢! Thread.yield(); } } System.out.println(Thread.currentThread().getName()+"结束了战斗!"); }}
package com.h.concurrent;public class KeyPersonThread 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.h.concurrent;/** * 隋唐演义大戏舞台 */public class Stage extends Thread { public void run(){ System.out.println("欢迎观看隋唐演义"); //让观众们安静片刻,等待大戏上演 try { Thread.sleep(5000); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println("大幕徐徐拉开"); try { Thread.sleep(5000); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println("话说隋朝末年,隋军与农民起义军杀得昏天黑地..."); ArmyRunnable armyTaskOfSuiDynasty = new ArmyRunnable(); ArmyRunnable armyTaskOfRevolt = new ArmyRunnable(); //使用Runnable接口创建线程 Thread armyOfSuiDynasty = new Thread(armyTaskOfSuiDynasty,"隋军"); Thread armyOfRevolt = new Thread(armyTaskOfRevolt,"农民起义军"); //启动线程,让军队开始作战 armyOfSuiDynasty.start(); armyOfRevolt.start(); //舞台线程休眠,大家专心观看军队厮杀 try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("正当双方激战正酣,半路杀出了个程咬金"); Thread mrCheng = new KeyPersonThread(); mrCheng.setName("程咬金"); System.out.println("程咬金的理想就是结束战争,使百姓安居乐业!"); //停止军队作战 //停止线程的方法 armyTaskOfSuiDynasty.keepRunning = false; armyTaskOfRevolt.keepRunning = false; try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } /* * 历史大戏留给关键人物 */ mrCheng.start(); //万众瞩目,所有线程等待程先生完成历史使命 try { mrCheng.join();//join()方法使得所有线程等待 调用join方法的线程结束 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("战争结束,人民安居乐业,程先生实现了积极的人生梦想,为人民作出了贡献!"); System.out.println("谢谢观看隋唐演义,再见!"); } public static void main(String[] args) { new Stage().start(); }}//Stage舞台继承了Thread类,其实它相当于一个总线程,用于控制多个线程协同工作的,yield()方法是让当前线程可以让出处理器,让多条线程可以同时进行的关键,join()方法就相当于等待线程,由于各个线程独立运行互不干扰,当它们同时进行的时候,会出现某个线程过早结束的情况,本例中的Stage总线程如果不在"程咬金"线程出现的时候使用join方法,它就会在启动了"程咬金"线程之后运行结束,导致舞台剧过早结束,所以用join方法来等待"程咬金"线程,只有当使用了join方法的线程运行完毕了之后,也就是等待"程咬金"线程运行完毕以后,才是舞台剧的谢幕
舞台、隋军、农民军是三个线程,舞台线程用于调度后者,线程其实就是用户自己定义的任务,所以才需要覆写run方法,或者用runnable初始化线程。
如何正确的停止java中的线程?
错误方法:stop(),会使线程戛然而止
正确方法:设置线程退出的标志
广为流传的错误方法:interrupt()
package com.h.concurrent;/** * Created by John on 2017/5/13. */public class WrongWayStopThread extends Thread{ public static void main(String[] args) { WrongWayStopThread thread = new WrongWayStopThread(); System.out.println("starting thread..."); thread.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("interrupting thread"); thread.interrupt(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("stoping application..."); } public void run(){ //while(true){ while(!this.isInterrupted()){//这里相当于设置了退出标志 System.out.println("thread is running"); //这里不使用Thread.sleep(1000)是有原因的 //long time = System.currentTimeMillis(); // while(System.currentTimeMillis()-time<1000){ // //减少屏幕输出的空循环 // } /** * 这里调用Thread.sleep(1000)会产生两个后果: * 1.当调用Thread.sleep(1000)方法时,会使当前线程进入block阻塞状态,此时再调用 * 该线程的thread.interrupt()方法会clear中断标志位,this.isInterrupted()就 不能返回正确的标志; * 2.hread.sleep(1000)会抛出ava.lang.InterruptedException */ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }}
package com.h.concurrent;/** * Created by John on 2017/5/13. */public class RightWayStopThread extends Thread{ volatile boolean keepRunning = true; public static void main(String[] args) { RightWayStopThread thread = new RightWayStopThread (); System.out.println("starting thread..."); thread.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // System.out.println("interrupting thread"); System.out.println("set exitFlag"); //thread.interrupt(); thread.keepRunning = false; try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("stoping application..."); } public void run(){ //while(true){ //while(!this.isInterrupted()){ while(keepRunning){ /*System.out.println("thread is running"); long time = System.currentTimeMillis(); while(System.currentTimeMillis()-time<1000){ //减少屏幕输出的空循环 }*/ /** * 这里调用Thread.sleep(1000)会产生两个后果: * 1.当调用Thread.sleep(1000)方法时,会使当前线程进入block阻塞状态,此时再调用 * 该线程的thread.interrupt()方法会clear中断标志位,this.isInterrupted()就不能返回正确的标志; * 2.hread.sleep(1000)会抛出ava.lang.InterruptedException */ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }}
线程交互
package com.h.concurrent.com.h.racecondition;/** * Created by John on 2017/5/13. ** * 宇宙的能量系统 * 遵循能量守恒定律: * 能量不会凭空创生或消失,只会从一处转移到另一处 */public class EnergySystem { //能量盒子,能量存贮的地方 private final double[] energyBoxes; private final Object lockObj = new Object(); /** * * @param n 能量盒子的数量 * @param initialEnergy 每个能量盒子初始含有的能量值 */ public EnergySystem(int n, double initialEnergy){ energyBoxes = new double[n]; for (int i = 0; i < energyBoxes.length; i++) energyBoxes[i] = initialEnergy; } /** * 能量的转移,从一个盒子到另一个盒子 * @param from 能量源 * @param to 能量终点 * @param amount 能量值 */ public void transfer(int from, int to, double amount){ synchronized(lockObj){// if (energyBoxes[from] < amount)// return; //while循环,保证条件不满足时任务都会被条件阻挡 //而不是继续竞争CPU资源 while (energyBoxes[from] < amount){ try { //条件不满足, 将当前线程放入Wait Set lockObj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.print(Thread.currentThread().getName()); energyBoxes[from] -= amount; System.out.printf("从%d转移%10.2f单位能量到%d", from, amount, to); energyBoxes[to] += amount; System.out.printf(" 能量总和:%10.2f%n", getTotalEnergies()); //唤醒所有在lockObj对象上等待的线程 lockObj.notifyAll(); } } /** * 获取能量世界的能量总和 */ public double getTotalEnergies(){ double sum = 0; for (double amount : energyBoxes) sum += amount; return sum; } /** * 返回能量盒子的长度 */ public int getBoxAmount(){ return energyBoxes.length; }}
package com.h.concurrent.com.h.racecondition;/** * Created by John on 2017/5/13. */public class EnergyTransferTask implements Runnable{ //共享的能量世界 private EnergySystem energySystem; //能量转移的源能量盒子下标 private int fromBox; //单次能量转移最大单元 private double maxAmount; //最大休眠时间(毫秒) private int DELAY = 10; public EnergyTransferTask(EnergySystem energySystem, int from, double max){ this.energySystem = energySystem; this.fromBox = from; this.maxAmount = max; } public void run() { try{ while (true){ int toBox = (int) (energySystem.getBoxAmount()* Math.random()); double amount = maxAmount * Math.random(); energySystem.transfer(fromBox, toBox, amount); Thread.sleep((int) (DELAY * Math.random())); } }catch (InterruptedException e){ e.printStackTrace(); } }}
package com.h.concurrent.com.h.racecondition;/** * Created by John on 2017/5/13. */public class EnergySystemTest { //将要构建的能量世界中能量盒子数量 public static final int BOX_AMOUNT = 100; //每个盒子初始能量 public static final double INITIAL_ENERGY = 1000; public static void main(String[] args){ EnergySystem eng = new EnergySystem(BOX_AMOUNT, INITIAL_ENERGY); for (int i = 0; i < BOX_AMOUNT; i++){ EnergyTransferTask task = new EnergyTransferTask(eng, i, INITIAL_ENERGY); Thread t = new Thread(task,"TransferThread_"+i); t.start(); } }}
0 0
- 进程与线程线程
- 进程与线程
- 进程与线程
- 进程与线程
- 进程与线程
- 进程与线程
- 进程与线程
- 进程与线程
- 进程与线程
- 进程与线程
- 进程与线程
- 进程与线程
- 线程与进程
- 线程与进程
- 进程与线程
- 进程与线程
- 线程与进程
- 进程与线程
- rm命令反向选择删除文件
- weblogic 安装和环境变量的设置(window)
- 2017 ,注定是一段珍贵的回忆!
- 基于《Selenium 2自动化测试实战》的学习笔记(10)—— 打印信息
- 《Java核心技术 卷1 基础知识 原书第9版》pdf:
- 进程与线程
- AngularJs入门
- JavaWeb
- 51nod1237 最大公约数之和 V3
- Ajax与Comet-JavaScript高级程序设计第21章读书笔记(2)
- hdu 3944 数学组合+帕斯卡定理
- Solr6 源码结构分析
- 使用Digital Ocean搭建Shadowsocks代理服务器
- web前端和web后端有什么区别