进程与线程

来源:互联网 发布:淘宝地推团队 编辑:程序博客网 时间: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