深入浅出Java多线程--慕课网笔记

来源:互联网 发布:路由器怎么映射端口 编辑:程序博客网 时间:2024/06/10 00:49
1-2java多线程基础概念介绍
  • 进程:程序(任务)的执行过程持有资源(共享内存,共享文件)和线程
  • 线程:qq聊天、收发文件

    *线程是系统中最小的执行单元
    同一进程中有多个线程
    线程共享进程的资源*

    *线程的交互
    互斥 同步*

java中线程的常用方法介绍:
java对线程的支持线程的创建和启动线程常用方法如何停止线程
java.lang

*class Thread
interface Runnable*

run()

Thread常用方法
  1. 线程的创建
    Thread()
    Thread(String name)
    Thread(Runnable target)
    Thread(Runnable target,String name)
  2. 线程的方法
    启动线程:
    start()
    线程休眠:
    sleep(long millis)
    sleep(long millis,intnanos)
    使其他线程等待当前线程终止:
    join()
    join(long millis)
    join(long millis,int nanos)
    当前运行线程释放处理器资源:
    yield()
  3. 获取线程引用
    返回当前运行的线程引用:
    currentThread()
2-2java线程-隋唐演义框架说明
//军队线程//模拟作战双方的行为public class ArmRunnable implements Runnable{}
ArmRunnable armyTaskOfSuiDynasty = new ArmyRunnable();ArmRunnable armyTaskOfarmyOfRevolt = new ArmyRunnable();
//使用Runnable接口创建线程Thread armyOfSuiDynasty = new Thread(armyTaskOfSuiDynasty,"随军");Thread armyOfRevolt = new Thread(armyTaskOfarmyOfRevolt,"农民起义军");
public class KeyPersonThread extends Thread{    public KeyPersonThread(String name){        super(name);    }    @Override    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()+"结束战斗!");    }   }
/** * 隋唐演义大戏舞台 */public class Stage extends Thread{}
综上所述:

*军队:ArmyRunnble
英雄人物:KeyPersonThread
舞台:Stage*

2-3Java线程-隋唐演义实战开发–演员简介
演员

*Mr.Thread
Ms.Runnable*

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{    @Override    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()+"的演出结束了!");    }}
2-4Java线程-隋唐演义实战开发–军队线程
2-5Java线程-隋唐演义实战开发–关键先生
//军队线程//模拟作战双方的行为public class ArmyRunnable implements Runnable {    //volatile保证了线程可以正确的读取其他线程写入的值    //可见性 ref JMM, happens-before原则    volatile boolean keepRunning = true;    @Override    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()+"结束了战斗!");    }}
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()+"结束了战斗!");    }}
/** * 隋唐演义大戏舞台 */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();        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("战争结束,人民安居乐业,程先生实现了积极的人生梦想,为人民作出了贡献!");        System.out.println("谢谢观看隋唐演义,再见!");    }    public static void main(String[] args) {        new Stage().start();    }}
3-1Java线程停止的错误方法–stop
not stop()方法
戛然而止完成了什么那些工作还没有做清理工作
3-2Java线程停止正确的方法–设置退出标志
 volatile boolean keepRunning = true;
3-3Java线程停止广为流传的错误方法–interrupt方法
interrupt方法初衷并不是停止线程
4-1Java线程交互之汽车人之忧:消失的能量
4-2Java线程交互之能量损失之谜:争用条件
Race Condition

*当多个线程同时共享访问同一数据(内存区域)时,每个线程都尝
试操作该数据,从而导致数据破坏(corrupted),这种现象称为争
用条件*。

4-3Java线程交互之互斥与同步:守恒的能量
/** * 宇宙的能量系统 * 遵循能量守恒定律: * 能量不会凭空创生或消失,只会从一处转移到另一处 */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;     }}
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();        }    }}
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();        }    }}
4-4Java线程交互之深入剖析互斥与同步
  • 互斥的实现:synchronized(intrinsic lock)
  • 同步的实现:wait()/notify()/notifyAll()

    *wait set
    critical section *

5-1总结及展望
  1. 如何创建线程及线程的基本操作
  2. 可见性及volatile关键字
  3. 争用条件
  4. 线程的互斥synchronized
  5. 线程的同步wait/notifyAll
扩展建议
  • Java Menory Model

    • MM描述了Java线程如何通过内存进行交互
    • happens-before
    • synchronized,volatile&final*
  • Locks&Condition

    • Java锁机制和等待条件的高级实现
    • java.util.concurrent.locks
  • 线程安全性

    • 原子性与可见性
    • java.util.concurrent.atomic
    • synchronized & volatile
    • DeadLocks
  • 多线程编程常用的交互模型

    • Producer-Consumer模型
    • Read-Write Lock模型
    • Future模型
    • Worker Thread模型
  • Java5中并发编程工具

    • java.util.concurrent
    • 线程池ExecutorService
    • Callable & Future
    • BlockingQueue
  • 书籍推荐

    • 《CORE JAVA》
    • 《JAVA CONCURRENCY IN PRACTICE》

深入浅出Java多线程视频

原创粉丝点击