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

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多线程视频

你可能感兴趣的:(慕课网笔记)