java基础---线程

(一)  

一、程序 进程 线程
1、程序:指令集 静态概念
2、进程:操作系统 调度程序 动态概念
3、线程:在进程内多条执行路径

(二)

一、继承Thread + run()
启动: 创建子类对象 +对象.start()

《java基础---线程》
《java基础---线程》

package com.zwj.thread;
/**
 * 模拟龟兔赛跑
 1、创建多线程  继承  Thread  +重写run(线程体)
 2、使用线程: 创建子类对象 + 对象.start()  线程启动
     
 * 
 * @author Administrator
 *
 */
public class Rabbit extends Thread {

    @Override
    public void run() {
        //线程体
        for(int i=0;i<10;i++){
            System.out.println("兔子跑了"+i+"步");
        }
        
        
    }
    
}
class Tortoise extends Thread {

    @Override
    public void run() {
        //线程体
        for(int i=0;i<10;i++){
            System.out.println("乌龟跑了"+i+"步");
        }
        
        
    }
    
}

Rabbit
《java基础---线程》
《java基础---线程》

package com.zwj.thread;
public class RabbitApp {

    /**
     * @param args
     */
    public static void main(String[] args) {
        //创建子类对象
        Rabbit rab = new Rabbit();
        Tortoise tor =new Tortoise();
        
        
        //调用start 方法
        rab.start(); //不要调用run方法
        //rab.run();
        tor.start();
        //tor.run();
        
        for(int i=0;i<10;i++){
            System.out.println("main==>"+i);
        }
    }

}
/*
乌龟跑了0步
乌龟跑了1步
兔子跑了0步
乌龟跑了2步
main==>1
乌龟跑了3步
兔子跑了1步
乌龟跑了4步
main==>2
乌龟跑了5步
兔子跑了2步
乌龟跑了6步
main==>3
乌龟跑了7步
兔子跑了3步
乌龟跑了8步
main==>4
乌龟跑了9步
兔子跑了4步
兔子跑了5步
兔子跑了6步
main==>5
兔子跑了7步
main==>6
兔子跑了8步
main==>7
兔子跑了9步
main==>8
main==>9
 */

RabbitApp

二、实现Runnable +run()
启动:使用静态代理
1、创建真实角色
2、创建代理角色 Thread+引用
3、代理角色.start()

推荐使用接口:
1、避免单继承局限性
2、便于共享资源

《java基础---线程》
《java基础---线程》

package com.zwj.thread;
/**
 推荐  Runnable 创建线程
 1)、避免单继承的局限性
 2)、便于共享资源
  
  
  使用 Runnable 创建线程
  1、类 实现 Runnable接口 +重写 run()   -->真实角色类
  2、启动多线程  使用静态代理
    1)、创建真实角色
    2)、创建代理角色 +真实角色引用
    3)、调用 .start() 启动线程
  
  
 * @author Administrator
 *
 */
public class Programmer implements Runnable {

    @Override
    public void run() {
        for(int i=0;i<1000;i++){
            System.out.println("一边敲helloworld....");
        }
    }

    

}

Programmer
《java基础---线程》
《java基础---线程》

package com.zwj.thread;
public class ProgrammerApp {

    /**
     * @param args
     */
    public static void main(String[] args) {
         //1)、创建真实角色
        Programmer pro =new Programmer();        
          //2)、创建代理角色 +真实角色引用
        Thread proxy =new Thread(pro);
          //3)、调用 .start() 启动线程
        proxy.start();
        
        for(int i=0;i<10;i++){
            System.out.println("一边聊qq...."+i);
        }
    }

}
/*
 一边聊qq....0
一边聊qq....1
一边聊qq....2
一边聊qq....3
一边聊qq....4
一边聊qq....5
一边敲helloworld....
一边敲helloworld....
一边敲helloworld....
一边敲helloworld....
一边敲helloworld....
一边敲helloworld....
一边敲helloworld....
一边敲helloworld....
一边敲helloworld....
一边敲helloworld....
一边聊qq....6
一边聊qq....7
一边聊qq....8
一边聊qq....9*/

ProgrammerApp
《java基础---线程》
《java基础---线程》

package com.zwj.thread;
/**
 * 方便共享资源
 * @author Administrator
 *
 */
public class Web12306 implements Runnable {
    private int num =10;

    @Override
    public void run() {
        while(true){
            if(num<=0){
                break; //跳出循环
            }
            System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
        }
    }
    
    public static void main(String[] args) {
        //真实角色
        Web12306 web = new Web12306();
        //代理
        Thread t1 =new Thread(web,"路人甲");
        Thread t2 =new Thread(web,"黄牛已");
        Thread t3 =new Thread(web,"攻城师");
        //启动线程
        t1.start();
        t2.start();
        t3.start();
    }
}/*路人甲抢到了10
路人甲抢到了8
路人甲抢到了7
路人甲抢到了6
路人甲抢到了5
路人甲抢到了4
路人甲抢到了3
路人甲抢到了2
路人甲抢到了1
黄牛已抢到了9
*/

Web12306

三、了解
通过Callable接口实现多线程
优点:可以获取返回值
Callable 和 Future接口
Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。
Callable和Runnable有几点不同:
(1)Callable规定的方法是call(),而Runnable规定的方法是run().
(2)call()方法可抛出异常,而run()方法是不能抛出异常的。
(3) Callable的任务执行后可返回值,运行Callable任务可拿到一个Future对象,而Runnable的任务是不能返回值的。
Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。
通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。
缺点 :繁琐
思路:
1)、创建 Callable实现类+重写call
2)、借助 执行调度服务 ExecutorService,获取Future对象
ExecutorService ser=Executors.newFixedThreadPool(2);
Future result =ser.submit(实现类对象)
3)、获取值 result.get()
4 )、 停止服务 ser.shutdownNow();

《java基础---线程》
《java基础---线程》

package com.zwj.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
 * 使用Callable创建线程
 * @author Administrator
 *
 */
public class Call {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //创建线程
        ExecutorService  ser=Executors.newFixedThreadPool(2);
        Race tortoise = new Race("老不死",1000);
        Race rabbit = new Race("小兔子",500);
        //获取值
        Future<Integer> result1 =ser.submit(tortoise) ;
        Future<Integer> result2 =ser.submit(rabbit) ;
        
        Thread.sleep(2000); //2秒
        tortoise.setFlag(false); //停止线程体循环
        rabbit.setFlag(false);
        
        int num1 =result1.get();
        int num2 =result2.get();
        System.out.println("乌龟跑了-->"+num1+"步");
        System.out.println("小兔子跑了-->"+num2+"步");
        //停止服务 
        ser.shutdownNow();

    }
}

class Race implements Callable<Integer>{
    private String name ; //名称
    private long time; //延时时间
    private boolean flag =true;
    private int step =0; //
    public Race() {
    }    

    public Race(String name) {
        super();
        this.name = name;
    }
    public Race(String name,long time) {
        super();
        this.name = name;
        this.time =time;
    }

    @Override
    public Integer call() throws Exception {
        while(flag){
            Thread.sleep(time); //延时
            step++;
        }
        return step;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    

    public long getTime() {
        return time;
    }

    public void setTime(long time) {
        this.time = time;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public int getStep() {
        return step;
    }

    public void setStep(int step) {
        this.step = step;
    }
    
}
/*乌龟跑了-->3步
小兔子跑了-->5步
*/

Call

 (三)

   《java基础---线程》

 

 1.新建状态(New): 
        当用new操作符创建一个线程时, 例如new Thread(r),线程还没有开始运行,此时线程处在新建状态。 当一个线程处于新生状态时,程序还没有开始运行线程中的代码

     2.就绪状态(Runnable)

        一个新创建的线程并不自动开始运行,要执行线程,必须调用线程的start()方法。当线程对象调用start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行run()方法。当start()方法返回后,线程就处于就绪状态。

        处于就绪状态的线程并不一定立即运行run()方法,线程还必须同其他线程竞争CPU时间,只有获得CPU时间才可以运行线程。因为在单CPU的计算机系统中,不可能同时运行多个线程,一个时刻仅有一个线程处于运行状态。因此此时可能有多个线程处于就绪状态。对多个处于就绪状态的线程是由Java运行时系统的线程调度程序(thread scheduler)来调度的。

    3.运行状态(Running)

        当线程获得CPU时间后,它才进入运行状态,真正开始执行run()方法.

    4. 阻塞状态(Blocked)

        线程运行过程中,可能由于各种原因进入阻塞状态:
        1>线程通过调用sleep方法进入睡眠状态;
        2>线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;
        3>线程试图得到一个锁,而该锁正被其他线程持有;
        4>线程在等待某个触发条件;
        ……           

        所谓阻塞状态是正在运行的线程没有运行结束,暂时让出CPU,这时其他处于就绪状态的线程就可以获得CPU时间,进入运行状态。

    5. 死亡状态(Dead)

        有两个原因会导致线程死亡:
        1) run方法正常退出而自然死亡,
        2) 一个未捕获的异常终止了run方法而使线程猝死。
        为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法。如果是可运行或被阻塞,这个方法返回true; 如果线程仍旧是new状态且不是       可运行的, 或者线程死亡了,则返回false.

二、停止线程
1、自然终止:线程体正常执行完毕
2、外部干涉:
1)、线程类中 定义 线程体使用的标识
2)、线程体使用该标识
3)、提供对外的方法改变该标识
4)、外部根据条件调用该方法即可

《java基础---线程》
《java基础---线程》

package com.zwj.status;
public class StopDemo01 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Study s =new Study();
        new Thread(s).start();
        
        //外部干涉   当main线程执行50次时,study线程停止运行
        for(int i=0;i<100;i++){
            if(50==i){ //外部干涉
                s.stop();
            }
            System.out.println("main.....-->"+i);
        }
    }

}
class Study implements Runnable{
     //1)、线程类中 定义 线程体使用的标识     
    private boolean flag =true;
    @Override
    public void run() {
        //2)、线程体使用该标识
        while(flag){
            System.out.println("study thread....");
        }
    }
    //3)、对外提供方法改变标识
    public void stop(){
        this.flag =false;
    }
    
}

StopDemo01

 

三、阻塞
1、join :合并线程, join()方法使调用该方法的线程在此之前执行完毕,也就是等待该方法的线程执行完毕后再往下继续执行。注意该方法也需要捕捉异常。

《java基础---线程》
《java基础---线程》

package com.zwj.status;

/**
 * join:合并线程
 * @author Administrator
 *
 */
public class JoinDemo01 extends Thread {

    /**
     * @param args
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException {
        JoinDemo01 demo = new JoinDemo01();
        Thread t = new Thread(demo); //新生
        t.start();//就绪
        //cpu调度 运行
        
        
        for(int i=0;i<10;i++){
            if(5==i){
                t.join(); //执行JoinDemo01线程  main线程等待上一个线程执行完后在执行...
            }
            System.out.println("main...."+i);
        }
    }
    @Override
    public void run() {
        for(int i=0;i<10;i++){
            System.out.println("join...."+i);
        }
    }

}
/*main....0
join....0
main....1
join....1
main....2
join....2
main....3
main....4
join....3
join....4
join....5
join....6
join....7
join....8
join....9
main....5
main....6
main....7
main....8
main....9
*/

JoinDemo01

2、yield:暂停自己的线程 static, 该方法与sleep()类似,只是不能由用户指定暂停多长时间,并且yield()方法只能让同优先级的线程有执行的机会。

《java基础---线程》
《java基础---线程》

package com.bjsxt.thread.status;

public class YieldDemo01 extends Thread {

    /**
     * @param args
     */
    public static void main(String[] args) {
        YieldDemo01 demo = new YieldDemo01();
        Thread t = new Thread(demo); //新生
        t.start();//就绪
        //cpu调度 运行
        
        
        for(int i=0;i<1000;i++){
            if(i%20==0){
                //暂停本线程 main
                Thread.yield();
            }
            System.out.println("main...."+i);
        }
    }
    
    @Override
    public void run() {
        for(int i=0;i<1000;i++){
            System.out.println("yield...."+i);
        }
    }

}

YieldDemo01

3、sleep:休眠,不释放锁
1)、与时间相关:倒计时
2)、模拟网络延时

3)、使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁。也就是说如果有synchronized同步快,其他线程仍然不能访问共享数据。注意该方法要捕捉异常。

《java基础---线程》
《java基础---线程》

package com.zwj.status;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 倒计时
 * 1、倒数10个数,一秒内打印一个
 * 2、倒计时
 * @author Administrator
 *
 */
public class SleepDemo01 {

    /**
     * @param args
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException {
        test1();
        Date endTime =new Date(System.currentTimeMillis()+10*1000);
        long end =endTime.getTime();
        while(true){
            //输出
            System.out.println(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(endTime));
            //等待一秒
            Thread.sleep(1000);
            //构建下一秒时间
            endTime =new Date(endTime.getTime()-1000);
            //10秒以内 继续 否则 退出
            if(end-10000>endTime.getTime()){
                break;
            }
        }
        
        
        
        
    }
    /*倒计时 10 */
    public static void test1() throws InterruptedException{
        int num =10;
        while(true){
            System.out.println(num--);
            Thread.sleep(1000); //暂停 1000毫秒等于1秒
            if(num<=0){
                break;
            }
        }
    }
/*10
9
8
7
6
5
4
3
2
1
2017-11-12 12:46:38
2017-11-12 12:46:37
2017-11-12 12:46:36
2017-11-12 12:46:35
2017-11-12 12:46:34
2017-11-12 12:46:33
2017-11-12 12:46:32
2017-11-12 12:46:31
2017-11-12 12:46:30
2017-11-12 12:46:29
2017-11-12 12:46:28*/    

}

SleepDemo01
《java基础---线程》
《java基础---线程》

package com.zwj.status;
/**
 * Sleep模拟 网络延时  线程不安全的类
 * @author Administrator
 *
 */
public class SleepDemo02 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        //真实角色
        Web12306 web= new Web12306();
        Web12306 web2 = new Web12306();
        //代理
        Thread t1 =new Thread(web,"路人甲");
        Thread t2 =new Thread(web,"黄牛已");
        Thread t3 =new Thread(web,"攻城师");
        //启动线程
        t1.start();
        t2.start();
        t3.start();
    }

}

class Web12306 implements Runnable {
    private int num =10;

    @Override
    public void run() {
        while(true){
            if(num<=0){
                break; //跳出循环
            }
            try {
                //500毫秒
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
        }
    }
    
    
}
/*黄牛已抢到了10
路人甲抢到了9
攻城师抢到了8
路人甲抢到了7
黄牛已抢到了6
攻城师抢到了5
黄牛已抢到了4
路人甲抢到了3
攻城师抢到了2
黄牛已抢到了0
路人甲抢到了1
攻城师抢到了-1*/

SleepDemo02

(四)

同步:并发 多个线程访问同一份资源 确保资源安全 –>线程安全
synchronized –>同步

一、同步块
synchronized(引用类型|this|类.class){

}
二、同步方法
synchronized

三、死锁: 过多的同步容易造成死锁

《java基础---线程》
《java基础---线程》

package com.zwj.synchronizeds;
public class SynDemo01 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        //真实角色
        Web12306 web= new Web12306();
        //代理
        Thread t1 =new Thread(web,"路人甲");
        Thread t2 =new Thread(web,"黄牛已");
        Thread t3 =new Thread(web,"攻城师");
        //启动线程
        t1.start();
        t2.start();
        t3.start();
        
        
        
        
    }

}
/**
 * 线程安全的类
 * @author Administrator
 *
 */
class Web12306 implements Runnable {
    private int num =10;
    private boolean flag =true;
    @Override
    public void run() {
        while(flag){
            //test5();
              test4();
            //test3();    线程安全  锁定正确  同步代码块
            //test2();    线程安全  锁定正确  同步方法 static synchronized
            //test1();    线程不安全
        }
    }
    
    public void test6(){
           
        if(num<=0){
            flag=false; //跳出循环
            return ;
        }
         //a  b  c     
        synchronized(this){
            try {
                Thread.sleep(500); //模拟 延时
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
        }
    }
    
    //线程不安全  锁定资源不正确
    public void test5(){
        //a  b  c
        synchronized((Integer)num){
            if(num<=0){
                flag=false; //跳出循环
                return ;
            }
            try {
                Thread.sleep(500); //模拟 延时
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
        }
    }
    
    
    
    //锁定范围不正确 线程不安全
    public void test4(){
        //   c  1
        synchronized(this){
            //b
            if(num<=0){
                flag=false; //跳出循环
                return ;
            }
        }
        // b
        try {
            Thread.sleep(500); //模拟 延时
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
    }//a -->1
    
    
    
    //线程安全  锁定正确  同步代码块
    public void test3(){
        //a  b  c
        synchronized(this){
            if(num<=0){
                flag=false; //跳出循环
                return ;
            }
            try {
                Thread.sleep(500); //模拟 延时
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
        }
    }
    //线程安全  锁定正确  同步方法 static synchronized
    public synchronized void test2(){
        if(num<=0){
            flag=false; //跳出循环
            return ;
        }
        try {
            Thread.sleep(500); //模拟 延时
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
    }
    
    
    //线程不安全
    public void test1(){
        if(num<=0){
            flag=false; //跳出循环
            return ;
        }
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
    }
}

SynDemo01
《java基础---线程》
《java基础---线程》

package com.zwj.synchronizeds;
/**
 * 单例创建的方式
 * 1、懒汉式
 * 1)、构造器私有化
 * 2)、声明私有的静态属性
 * 3)、对外提供访问属性的静态方法,确保该对象存在
 * 
 * @author Administrator
 *
 */
public class MyJvm {
    private static MyJvm instance;
    private MyJvm(){
        
    }
    public static MyJvm getInstance (){
        if(null==instance){ //提供效率
            synchronized(MyJvm.class){
                if(null==instance){ //安全
                    instance =new MyJvm();
                }
            }
        }
        return instance;
    }
    

}
/**
 * 饿汉式
   1)、构造器私有化 
 * 2)、声明私有的静态属性,同时创建该对象
 * 3)、对外提供访问属性的静态方法
 * @author Administrator
 *
 */
class MyJvm2 {
    private static MyJvm2 instance =new MyJvm2();
    private MyJvm2(){
        
    }
    public static MyJvm2 getInstance (){        
        return instance;
    }

}
/**
 * 类在使用的时候加载 ,延缓加载时间
 * @author Administrator
 *
 */
class MyJvm3 {
    private static class JVMholder{
        private static MyJvm3 instance =new MyJvm3();
    }
    private MyJvm3(){
        
    }
    //不调用此方法就不会加载jvmholder静态内部类
    public static MyJvm3 getInstance (){        
        return JVMholder.instance;
    }

}

MyJvm
《java基础---线程》
《java基础---线程》

package com.zwj.synchronizeds;

/**
 * 单例设计模式:确保一个类只有一个对象
 * @author Administrator
 *
 */
public class SynDemo02 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        JvmThread thread1 = new JvmThread(100);
        JvmThread thread2 = new JvmThread(500);
        thread1.start();
        thread2.start();
        
    }

}
class JvmThread extends Thread{
    private long time;
    public JvmThread() {
    }
    public JvmThread(long time) {
        this.time =time;
    }
    @Override
    public void run() {        
        System.out.println(Thread.currentThread().getName()+"-->创建:"+Jvm.getInstance(time));
    }
}


/**
 * 单例设计模式
 * 确保一个类只有一个对象
 * 懒汉式  double checking
 * 1、构造器私有化,避免外部直接创建对象
 * 2、声明一个私有的静态变量
 * 3、创建一个对外的公共的静态方法 访问该变量,如果变量没有对象,创建该对象
 */
class Jvm {
    //声明一个私有的静态变量
    private static Jvm instance =null;    
    //构造器私有化,避免外部直接创建对象
    private Jvm(){
        
    }
    //创建一个对外的公共的静态方法 访问该变量,如果变量没有对象,创建该对象
    public static Jvm getInstance(long time){
        // c d e  -->效率  提供 已经存在对象的访问效率
        if(null==instance){    
            // a b
            synchronized(Jvm.class){
                if(null==instance ){
                    try {
                        Thread.sleep(time); //延时 ,放大错误
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    instance =new Jvm();
                }
            }
      }//a
      return instance;
    }
    
    
    public static Jvm getInstance3(long time){
        //a b c d e  -->效率不高 c  存在对象也需要等待
        synchronized(Jvm.class){
            if(null==instance ){
                try {
                    Thread.sleep(time); //延时 ,放大错误
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                instance =new Jvm();
            }
            return instance;
        }
    }
    
    
    public static synchronized Jvm getInstance2(long time){
        if(null==instance ){
            try {
                Thread.sleep(time); //延时 ,放大错误
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            instance =new Jvm();
        }
        return instance;
    }
    
    
    
    public static Jvm getInstance1(long time){
        if(null==instance ){
            try {
                Thread.sleep(time); //延时 ,放大错误
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            instance =new Jvm();
        }
        return instance;
    }
}

SynDemo02
《java基础---线程》
《java基础---线程》

package com.zwj.synchronizeds;
/**
 * 过多的同步方法可能造成死锁
 * @author Administrator
 *
 */
public class SynDemo03 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Object g =new Object();
        Object m = new Object();
        Test t1 =new Test(g,m);
        Test2 t2 = new Test2(g,m);
        Thread proxy = new Thread(t1);
        Thread proxy2 = new Thread(t2);
        proxy.start();
        proxy2.start();
    }

}
class Test implements Runnable{
    Object goods ;
    Object money ;
    
    public Test(Object goods, Object money) {
        super();
        this.goods = goods;
        this.money = money;
    }

    @Override
    public void run() {
        while(true){
            test();
        }
    }
    
    public void test(){
        synchronized(goods){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized(money){
                
            }
            
        }
        System.out.println("一手给钱");
    }
    
    
    
    
    
    
    
}

class Test2  implements Runnable{
    Object goods ;
    Object money ;
    public Test2(Object goods, Object money) {
        super();
        this.goods = goods;
        this.money = money;
    }

    @Override
    public void run() {
        while(true){
            test();
        }
    }
    
    public void test(){
        synchronized(money){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized(goods){
                
            }
            
        }
        System.out.println("一手给货");
    }
    
    
    
}

SynDemo03

 (五)

信号灯法
一、 wait() :等待,释放锁 sleep 不释放锁
二、notify()/notifyAll():唤醒
与 synchronized 一起使用

《java基础---线程》
《java基础---线程》

package com.zwj.pro;
/**
 一个场景,共同的资源
  生产者消费者模式 信号灯法
 wait() :等待,释放锁   sleep 不释放锁
 notify()/notifyAll():唤醒
  与 synchronized
 * @author Administrator
 *
 */
public class Movie {
    private String pic ;
    //信号灯
    //flag -->T 生产生产,消费者等待 ,生产完成后通知消费
    //flag -->F 消费者消费 生产者等待, 消费完成后通知生产
    private boolean flag =true;
    /**
     * 播放
     * @param pic
     */
    public synchronized void play(String pic){
        if(!flag){ //生产者等待
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //开始生产
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("生产了:"+pic);
        //生产完毕        
        this.pic =pic;
        //通知消费
        this.notify();
        //生产者停下
        this.flag =false;
    }
    
    public synchronized void watch(){
        if(flag){ //消费者等待
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //开始消费
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("消费了"+pic);
        //消费完毕
        //通知生产
        this.notifyAll();
        //消费停止
        this.flag=true;
    }
}

Movie
《java基础---线程》
《java基础---线程》

package com.zwj.pro;
/**
 * 生产者
 * @author Administrator
 *
 */
public class Player implements Runnable {
    private Movie m ;
    
    public Player(Movie m) {
        super();
        this.m = m;
    }

    @Override
    public void run() {
        for(int i=0;i<20;i++){
            if(0==i%2){
                m.play("左青龙"+i);
            }else{
                m.play("右白虎"+i);
            }
        }
    }

}

Player
《java基础---线程》
《java基础---线程》

package com.zwj.pro;
public class Watcher implements Runnable {
    private Movie m ;
    
    public Watcher(Movie m) {
        super();
        this.m = m;
    }

    @Override
    public void run() {
        for(int i=0;i<20;i++){
            m.watch();
        }
    }

}

Watcher
《java基础---线程》
《java基础---线程》

package com.zwj.pro;


public class App {
    public static void main(String[] args) {
        //共同的资源
        Movie m = new Movie();
        
        //多线程
        Player p = new Player(m);
        Watcher w = new Watcher(m);
        
        new Thread(p).start();        
        new Thread(w).start();
    }
}
/*生产了:左青龙0
消费了左青龙0
生产了:右白虎1
消费了右白虎1
生产了:左青龙2
消费了左青龙2
生产了:右白虎3
消费了右白虎3
生产了:左青龙4
消费了左青龙4
生产了:右白虎5
消费了右白虎5
生产了:左青龙6
消费了左青龙6
生产了:右白虎7*/

App

 

《java基础---线程》
《java基础---线程》

package com.zwj.pro;

public class TestProduce {
    public static void main(String[] args) {
        SyncStack sStack = new SyncStack();
        Shengchan sc = new Shengchan(sStack);
        Xiaofei xf = new Xiaofei(sStack);
        sc.start();
        xf.start();
    }
}

class Mantou {
    int id;
    Mantou(int id){
        this.id=id;
    }
}

class SyncStack{
    int index=0;
    Mantou[] ms = new Mantou[10];
    
    public synchronized void push(Mantou m){
        while(index==ms.length){
            try {
                this.wait(); 
                //wait后,线程会将持有的锁释放。sleep是即使睡着也持有互斥锁。
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.notify(); //唤醒在当前对象等待池中等待的第一个线程。notifyAll叫醒所有在当前对象等待池中等待的所有线程。
        //如果不唤醒的话。以后这两个线程都会进入等待线程,没有人唤醒。
        ms[index]=m;
        index++;
    }
    public synchronized Mantou pop(){
        while(index==0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.notify();
        index--;
        return ms[index];
    }
}

class Shengchan extends Thread{
    SyncStack ss = null;
    
    public Shengchan(SyncStack ss) {
        this.ss=ss;
    }
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("造馒头:"+i);
            Mantou m = new Mantou(i);
            ss.push(m);
        }
    }
}

class Xiaofei extends Thread{
    SyncStack ss = null;
    
    public Xiaofei(SyncStack ss) {
        this.ss=ss;
    }
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            Mantou m = ss.pop();
            System.out.println("吃馒头:"+i);
            
        }
    }
}

TestProduce

(六) 

了解
Timer()
schedule(TimerTask task, Date time)
schedule(TimerTask task, Date firstTime, long period)
自学  juc  quartz

 

《java基础---线程》
《java基础---线程》

package com.zwj.pro;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
/**
    了解
  Timer() 
  schedule(TimerTask task, Date time) 
  schedule(TimerTask task, Date firstTime, long period) 
  自学 quartz
 * @author Administrator
 *
 */
public class TimeDemo01 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Timer timer =new Timer();
        //从new Date(System.currentTimeMillis()+1000)开始执行200次
        timer.schedule(new TimerTask(){

            @Override
            public void run() {
                System.out.println("so easy....");
            }}, new Date(System.currentTimeMillis()+1000), 200);
    }

}

TimeDemo01

 

    原文作者:周无极
    原文地址: https://www.cnblogs.com/ou-pc/p/7821116.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞