zoukankan      html  css  js  c++  java
  • java基础---线程

    (一)  

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

    (二)

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

    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
    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、便于共享资源

    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
    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
    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();

    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

     (三)

       

     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)、外部根据条件调用该方法即可

    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()方法使调用该方法的线程在此之前执行完毕,也就是等待该方法的线程执行完毕后再往下继续执行。注意该方法也需要捕捉异常。

    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()方法只能让同优先级的线程有执行的机会。

    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同步快,其他线程仍然不能访问共享数据。注意该方法要捕捉异常。

    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
    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

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

    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
    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
    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
    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 一起使用

    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
    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
    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
    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
    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

    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
  • 相关阅读:
    从Python到Web开发
    源码安装缺少configure文件
    5
    4
    3
    2
    42
    1
    18
    41
  • 原文地址:https://www.cnblogs.com/ou-pc/p/7821116.html
Copyright © 2011-2022 走看看