zoukankan      html  css  js  c++  java
  • 《Java多线程编程核心技术》读后感(十一)

     

     

     

     

     

     

    方法join的使用

    在很多情况下,主线程创建并启动子线程,如果子线程中要进行大量的耗时运算,主线程往往将早于子线程结束之前结束。这时,如果主线程想等待子线程执行完之后再结束,比如子线程处理一个数据,主线程要取得这个数据中的值,就要用到join()方法了。

    学习join前的铺垫

    package Third;
    
    public class MyThread extends Thread {
    
        @Override
        public void run() {
            try {
                int secondValue = (int) (Math.random() * 10000);
                System.out.println(secondValue);
                Thread.sleep(secondValue);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
    }
    package Third;
    
    public class Test {
    
        public static void main(String[] args) {
    
            MyThread threadTest = new MyThread();
            threadTest.start();
    
            // Thread.sleep(?)
            System.out.println("我想当threadTest对象执行完毕后我再执行");
            System.out.println("但上面代码中的sleep()中的值应该写多少呢?");
            System.out.println("答案是:根据不能确定:)");
        }
    
    }

    sleep()多少不能确定

    用join()方法来解决

    package Third;
    
    public class Test {
    
        public static void main(String[] args) {
            try {
                MyThread threadTest = new MyThread();
                threadTest.start();
                threadTest.join();
    
                System.out.println("我想当threadTest对象执行完毕后我再执行,我做到了");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }

    方法join的作用是使所属的线程对象X正常执行run()方法中的任务,而使当前线程z进行无限期的阻塞,等待线程x销毁后再继续执行线程z后面的代码。

    方法join具有使线程排队运行的作用,有些类似同步的运行效果。join与synchronized的区别是:join在内部使用wait()方法进行等待,而synchronized关键字使用的是“”对象监视器“”原理做为同步。

    方法join与异常

    在join过程中,如果当前线程对象被中断,则当前线程出现异常

    package Third;
    
    public class ThreadA extends Thread {
        @Override
        public void run() {
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                String newString = new String();
                Math.random();
            }
        }
    }
    package Third;
    
    public class ThreadB extends Thread {
    
        @Override
        public void run() {
            try {
                ThreadA a = new ThreadA();
                a.start();
                a.join();
    
                System.out.println("线程B在run end处打印了");
            } catch (InterruptedException e) {
                System.out.println("线程B在catch处打印了");
                e.printStackTrace();
            }
        }
    
    }
    package Third;
    
    public class ThreadC extends Thread {
    
        private ThreadB threadB;
    
        public ThreadC(ThreadB threadB) {
            super();
            this.threadB = threadB;
        }
    
        @Override
        public void run() {
            threadB.interrupt();
        }
    
    }

    方法join(long)使用

    参数是设定等待的时间

    package Third;
    
    public class MyThread extends Thread {
    
        @Override
        public void run() {
            try {
                System.out.println("begin Timer=" + System.currentTimeMillis());
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    package Third;
    
    public class Test {
    
        public static void main(String[] args) {
            try {
                MyThread threadTest = new MyThread();
                threadTest.start();
    
                 threadTest.join(2000);//只等2秒
                //Thread.sleep(2000);
    
                System.out.println("  end timer=" + System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }

    package Third;
    
    public class Test {
    
        public static void main(String[] args) {
            try {
                MyThread threadTest = new MyThread();
                threadTest.start();
    
                //threadTest.join(2000);//只等2秒
                Thread.sleep(2000);
    
                System.out.println("  end timer=" + System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }

     方法join(long)与sleep(long)的区别

    方法join(long)的功能在内部是使用wait(long)方法来实现的,所以join(long)方法具有释放锁的特点。

    从源代码中可以了解到,当执行wait(long)方法后,当前线程的锁被释放,那么其他线程就可以调用此线程中的同步方法了。

    而Thread.sleep(long)方法却不释放锁,下面的实验证Thread.sleep(long)不释放锁的特点

    package Third;
    
    public class ThreadA extends Thread {
    
        private ThreadB b;
    
        public ThreadA(ThreadB b) {
            super();
            this.b = b;
        }
    
        @Override
        public void run() {
            try {
                synchronized (b) {
                    b.start();
                    Thread.sleep(6000);
                    // Thread.sleep()不释放锁
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    package Third;
    
    public class ThreadB extends Thread {
    
        @Override
        public void run() {
            try {
                System.out.println("   b run begin timer="
                        + System.currentTimeMillis());
                Thread.sleep(5000);
                System.out.println("   b run   end timer="
                        + System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        synchronized public void bService() {
            System.out.println("打印了bService timer=" + System.currentTimeMillis());
        }
    
    }
    package Third;
    
    public class ThreadC extends Thread {
    
        private ThreadB threadB;
    
        public ThreadC(ThreadB threadB) {
            super();
            this.threadB = threadB;
        }
    
        @Override
        public void run() {
            threadB.bService();
        }
    
    }
    package Third;
    
    public class Run {
    
        public static void main(String[] args) {
    
            try {
                ThreadB b = new ThreadB();
    
                ThreadA a = new ThreadA(b);
                a.start();
    
                Thread.sleep(1000);
    
                ThreadC c = new ThreadC(b);
                c.start();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }

    下面验证Thread.sleep(long)释放锁的特点

    更改上面的ThreadA.java

    package Third;
    
    public class ThreadA extends Thread {
    
        private ThreadB b;
    
        public ThreadA(ThreadB b) {
            super();
            this.b = b;
        }
    
        @Override
        public void run() {
            try {
                synchronized (b) {
                    b.start();
                    b.join();// 说明join释放锁了
                    for (int i = 0; i < Integer.MAX_VALUE; i++) {
                        String newString = new String();
                        Math.random();
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    方法join()后面的代码提前运行:出现意外

    package Third;
    
    public class ThreadA extends Thread {
        private ThreadB b;
    
        public ThreadA(ThreadB b) {
            super();
            this.b = b;
        }
    
        @Override
        public void run() {
            try {
                synchronized (b) {
                    System.out.println("begin A ThreadName="
                            + Thread.currentThread().getName() + "  "
                            + System.currentTimeMillis());
                    Thread.sleep(5000);
                    System.out.println("  end A ThreadName="
                            + Thread.currentThread().getName() + "  "
                            + System.currentTimeMillis());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    package Third;
    
    public class ThreadB extends Thread {
        @Override
        synchronized public void run() {
            try {
                System.out.println("begin B ThreadName="
                        + Thread.currentThread().getName() + "  "
                        + System.currentTimeMillis());
                Thread.sleep(5000);
                System.out.println("  end B ThreadName="
                        + Thread.currentThread().getName() + "  "
                        + System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    package Third;
    
    public class Run1 {
        public static void main(String[] args) {
            try {
                ThreadB b = new ThreadB();
                ThreadA a = new ThreadA(b);
                a.start();
                b.start();
                b.join(2000);
                System.out.println("                    main end "
                        + System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    方法join()后面的代码提前运行:解释意外

    package Third;
    
    public class RunFirst {
    
        public static void main(String[] args) {
            ThreadB b = new ThreadB();
            ThreadA a = new ThreadA(b);
            a.start();
            b.start();
            System.out.println("   main end=" + System.currentTimeMillis());
        }
    
    }

     

     

  • 相关阅读:
    macOS 在终端中使用 adb命令,每次都要source ~/.bash_profile 才生效
    判断一个数是奇数还是偶数?
    使用SQL Server 扩展事件来创建死锁的跟踪
    sql server阻塞(block)处理
    sqlserver的CTE实现递归查询
    sqlserver 行转列
    sqlserver字符串多行合并为一行
    git alias 配置别名,让命令更简洁,提高效率
    vim 快捷键
    Git bash 命令行中的快捷键
  • 原文地址:https://www.cnblogs.com/Michael2397/p/7858057.html
Copyright © 2011-2022 走看看