zoukankan      html  css  js  c++  java
  • 新手学习多线程的详细思路和流程

      最近在博客园中逛,看到多线程想学习一下,虽然作者本人感觉挺详细的,但对于新手没学过多线程理解还是有难度的,最多也就是明白大概意思,自己写还是一片空白,我看过多个博客以后觉得还需要打代码才能彻底理解多线程,以下以一个经典多线程题目为例,一个菜鸟解题的具体步骤:

      题目:建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。

      1.看到三个线程,同时运行,交替打印,和大神解答写的各种流程、sleep、synchronized、wait、notify一阵头痛。还是自己慢慢来,打印10个A先。。

    package main;
    
    /**
     * 
     * 多线程题目解答
     * @author 光
     * @version 2015年11月20日 上午10:46:53
     *
     */
    public class ManyThreadPrint implements Runnable {
        
        public String name;
        
        public ManyThreadPrint(String name){
            this.name=name;
        }
    
        @Override
        public void run() {
            int count = 10;
            while(count > 0){
                System.out.print(name);
                count--;
            }
        }
    
        public static void main(String[] args) {
            ManyThreadPrint mtpa = new ManyThreadPrint("A");
            new Thread(mtpa).start();
        }
    }

      解析:使用实现Runnable接口的方式使用线程,main方法中添加实例使用构造器传参A,重写run()方法中循环打印10次

      运行结果如下:

    AAAAAAAAAA
    

      2.十次A打印完成,哈哈,把B和C打印以下试试

    package main;
    
    /**
     * 
     * 多线程题目解答
     * @author 光
     * @version 2015年11月20日 上午10:46:53
     *
     */
    public class ManyThreadPrint implements Runnable {
        
        public String name;
        
        public ManyThreadPrint(String name){
            this.name=name;
        }
    
        @Override
        public void run() {
            int count = 10;
            while(count > 0){
                System.out.print(name);
                count--;
            }
        }
    
        public static void main(String[] args) {
            ManyThreadPrint mtpa = new ManyThreadPrint("A");
            ManyThreadPrint mtpb = new ManyThreadPrint("B");
            ManyThreadPrint mtpc = new ManyThreadPrint("C");
            new Thread(mtpa).start();
            new Thread(mtpb).start();
            new Thread(mtpc).start();
        }
    }

      解析:只是在main方法中添加两个实例把B和C穿进去,添加两个线程执行

      运行结果如下:

    AAAAAAAAAABBBBBBBBBBCCCCCCCCCC
    

      手贱又运行一下:

    AAAAAAAAAACCCCCCCCCCBBBBBBBBBB
    

      这怎么回事。。在试一下:

    ABBBBBBBBBBAAAAAAAAACCCCCCCCCC
    

      好吧,结果10个A,10个B,10个C全部打印出来了,就是结果不固定。

      3.查了一下资料,原来是3个线程同时执行,顺序不固定。只好让后面的线程先等一下再执行:

    package main;
    
    /**
     * 
     * 多线程题目解答
     * @author 光
     * @version 2015年11月20日 上午10:46:53
     *
     */
    public class ManyThreadPrint implements Runnable {
        
        public String name;
        
        public ManyThreadPrint(String name){
            this.name=name;
        }
    
        @Override
        public void run() {
            int count = 10;
            while(count > 0){
                System.out.print(name);
                count--;
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            ManyThreadPrint mtpa = new ManyThreadPrint("A");
            ManyThreadPrint mtpb = new ManyThreadPrint("B");
            ManyThreadPrint mtpc = new ManyThreadPrint("C");
            new Thread(mtpa).start();
            Thread.sleep(10);
            new Thread(mtpb).start();
            Thread.sleep(10);
            new Thread(mtpc).start();
            Thread.sleep(10);
        }
    }

      解析:有一点需要注意,Thread.sleep(10);是下一个线程启动需要等待的时间,由于最后结果需要交替打印,所以第三个线程执行后也有一个等待,相当于下轮的第一个线程等待。

      结果如下(执行几次都一样):

    AAAAAAAAAABBBBBBBBBBCCCCCCCCCC
    

      3.接下来就是交替ABC按照大神的方法,建立3个对象,虽然是三个普通的Object,却在run()中通过同步、等待、释放锁来实现线程的执行顺序,先看一下代码:

    package main;
    
    /**
     * 
     * 多线程题目解答
     * @author 光
     * @version 2015年11月20日 上午10:46:53
     *
     */
    public class ManyThreadPrint implements Runnable {
        
        public String name;
        public Object prev;
        public Object self;
        
        public ManyThreadPrint(String name, Object prev, Object self) {
            this.name = name;
            this.prev = prev;
            this.self = self;
        }
    
    
        @Override
        public void run() {
            int count = 10;
            while(count > 0){
                synchronized (prev) {
                    synchronized (self) {
                        System.out.print(name);
                        count--;
                        self.notify();
                    }
                    try {
                        prev.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            Object a = new Object(); 
            Object b = new Object();
            Object c = new Object();
            ManyThreadPrint mtpa = new ManyThreadPrint("A",c,a);
            ManyThreadPrint mtpb = new ManyThreadPrint("B",a,b);
            ManyThreadPrint mtpc = new ManyThreadPrint("C",b,c);
            new Thread(mtpa).start();
            Thread.sleep(10);
            new Thread(mtpb).start();
            Thread.sleep(10);
            new Thread(mtpc).start();
            Thread.sleep(10);
        }
    }

      解析:

      改变构造器,每次创建实例是除了打印的字符串,还有两个对象,这一点要注意,这两个对象只是普通的Object,跟线程没一毛线关系,只是通过线程对对象锁的操作来控制流程。关键代码在run()中的循环里面,一点一点来。

      这里synchronized (self)、synchronized (prev),self当前对象锁,prev前一个(前缀)对象锁,当线程获取两个对象锁时执行打印;需要注意。将synchronized (self)放入synchronized (prev)中表示打印A线程执行后,进入等待前置C对象的线程池里面,这样在打印C时唤醒一下C对象,那么打印C完成后就会立刻打印A,不过这样执行需要保证3个线程的启动顺序,即main方法中的Thread.sleep(10)。启动打印A线程时,打印A,唤醒自己,进入等待C的线程池,释放AC。当3个线程按照启动顺序完成时,即打印C线程完成后,会立刻打印A,打印A线程完成后,立刻打印B,依照顺序循环。

      也就是说,在3个线程启动完成后,已经将打印A的线程进入等待C对象的线程池里;将打印B的线程进入等待A对象的线程池里;将打印C的线程进入等待B对象的线程池里。这时按照打印A线程、打印B线程、打印C线程的顺序执行,就保证下一轮以打印A线程开始,从而保证以后打印顺序。

      在自己打代码的过程中发现了很多感觉看懂的时候没发现的东西,所以,学东西,最好自己要手打一遍。

  • 相关阅读:
    链表总结
    源码,反码,补码,位运算
    JAVA打印乘法口诀表
    JAVA打印空三角形
    JAVA打印三角形
    列表,元组,字典,集合类型
    for 循环 ,数字类型,以及字符串类型
    基本运算符补充,流程控制if判断与while循环
    内存管理,数据类型的基本使用与基本运算符(python2中与用户交互)
    编程的分类,以及运行python解释器的原理,最后变量
  • 原文地址:https://www.cnblogs.com/xiaoguangit/p/4991825.html
Copyright © 2011-2022 走看看