zoukankan      html  css  js  c++  java
  • (1)Java多线程编程核心——Java多线程技能

    1、为什么要使用多线程?多线程的优点?

    提高CPU的利用率

    2、什么是多线程?

    3、Java实现多线程编程的两种方式?

    a、继承Thread类

    public class MyThread01 extends Thread {
        @Override
        public void run() {
            super.run();
            System.out.println("MyThread01");
        }

        public static void main(String[] args){
            MyThread01 myThread01 = new MyThread01();
            myThread01.start();
            System.out.println("运行结束");
        }
    }

    运行结束

    MyThread01

    多次调用start(),抛异常

    public class MyThread01 extends Thread {
        @Override
        public void run() {
            super.run();
            System.out.println("MyThread01");
        }

        public static void main(String[] args){
            MyThread01 myThread01 = new MyThread01();
            myThread01.start();
            myThread01.start();
            System.out.println("运行结束");
        }
    }

    Exception in thread "main" java.lang.IllegalThreadStateException

             at java.lang.Thread.start(Thread.java:705)

             at com.season.testthread.MyThread01.main(MyThread01.java:13)

    MyThread01

    b、实现Runnable接口

    public class MyRunnable01 implements Runnable {
        @Override
        public void run() {
            System.out.println("MyRunnable01 run().....");
        }

        public static void main(String[] args){
            Runnable runnable = new MyRunnable01();
            Thread thread = new Thread(runnable);
            thread.start();
            System.out.println("main().....");
        }
    }

    main().....

    MyRunnable01 run().....

    4、两种方式的对比?

    Thread类本身实现了Runnable接口;

    使用Thread类方式创建线程,最大的局限是不支持多继承

    5、start() 和 直接调用run() 有什么异同?

    Thread.java类中的 start() 通知“线程规划器”此线程已经准备就绪,等待调用线程对象的 run()。run()是由调用线程执行,必须等待 run() 代码执行完成才能执行后面代码,不具有异步效果。

    6、非线程安全?

    多个线程对同一对象中的同一实例变量进行操作时会出现值被更改、值不同步的情况,进而影响程序的执行流程。

    (1)不共享数据情况

    public class MyThread02 extends Thread {
        private int count = 5;
        public MyThread02(String name){
            this.setName(name);
        }

        @Override
        public void run() {
            super.run();
            while (count > 0){
                count--;
                System.out.println("由 " + Thread.currentThread().getName() + " 计算,count=" + count);
            }
        }

        public static void main(String[] args){
            MyThread02 a = new MyThread02("a");
            MyThread02 b = new MyThread02("b");
            MyThread02 c = new MyThread02("c");
            a.start();
            b.start();
            c.start();
        }
    }

    由 a 计算,count=4

    由 a 计算,count=3

    由 a 计算,count=2

    由 a 计算,count=1

    由 a 计算,count=0

    由 c 计算,count=4

    由 c 计算,count=3

    由 c 计算,count=2

    由 c 计算,count=1

    由 c 计算,count=0

    由 b 计算,count=4

    由 b 计算,count=3

    由 b 计算,count=2

    由 b 计算,count=1

    由 b 计算,count=0

    (2)共享数据情况

    public class MyThread03 extends Thread {
        private int count = 5;

        @Override
        public void run() {
            super.run();
            while (count > 0){
                count--;
                System.out.println("由 " + Thread.currentThread().getName() + " 计算,count=" + count);
            }
        }

        public static void main(String[] args){
            MyThread03 myThread03 = new MyThread03();
            Thread a = new Thread(myThread03, "a");
            Thread b = new Thread(myThread03, "b");
            Thread c = new Thread(myThread03, "c");
            Thread d = new Thread(myThread03, "d");
            Thread e = new Thread(myThread03, "e");
            a.start();
            b.start();
            c.start();
            d.start();
            e.start();
        }
    }

    由 c 计算,count=3

    由 c 计算,count=2

    由 c 计算,count=1

    由 c 计算,count=0

    由 a 计算,count=3

    7、怎么解决非线程安全问题?

    使用 synchronized 关键字:当一个线程要执行同步方法里面的代码时,线程首先尝试去拿这把锁,如果能拿到,这个线程就可以执行synchronized 里面的代码。如果拿不到,那么这个线程就会不断尝试拿这把锁,直到拿到为止,而且是有多个线程同时去争抢这把锁。

    8、API

    currentThread() 返回代码段正在被哪个线程调用的信息。

    isAlive() 判断当前线程是否处于活动状态(线程已经启动且尚未终止)。

    sleep() 在指定的毫秒内让当前“正在执行的线程”休眠(暂停执行)

    getId() 取得线程的唯一标识

    yield() 放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间。但放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片。

    9、怎么停止线程?

    1)、使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。

    2)、使用 stop() 强行终止线程,不推荐使用这种方法,因为 stop 和 suspend 及 resume 一样,都是作废过期的方法,使用它们可能产生不可预料的结果。如果强行让线程停止则可能使一些请理性的工作得不到完成。另外一个情况就是对锁定的对象进行了“解锁”,导致数据得不到同步处理,出现数据不一致问题。

    3)、使用 interrupt() 中断线程。

    interrupt() 仅仅是在当前线程中打了一个停止标记,并不是真的停止线程。

    this.interrupted() 测试当前线程是否已经中断状态,执行后具有将状态标识置清除为false的功能。当前线程是指运行 this. Interrupted() 的线程。interrupted() 具有清除状态的功能,所以第二次调用interrupted() 返回值是false。

    this.isInterrupted() 测试线程Thread对象是否已经是中断状态,但不清除状态标识。

    a、能停止的线程——异常法

    public class MyThread04 extends Thread {

       @Override

       public void run() {

          for(int i = 0; i < 500000; i++){

              if(this.interrupted()){

                 System.out.println("已经是停止状态,立即退出!");

                 break;

              }

              System.out.println("i = " + (i + 1));

          }

          System.out.println("for下面语句运行,线程并未停止。");

       }

      

       public static void main(String[] args) {

          try {

              MyThread04 myThread04 = new MyThread04();

              myThread04.start();

              Thread.sleep(2000);

              myThread04.interrupt();

          } catch (InterruptedException e) {

              System.out.println("main catch{}...");

              e.printStackTrace();

          }

          System.out.println("main() end ....");

       }

    }

    i = 207023

    main() end ....

    已经是停止状态,立即退出!

    for下面语句运行,线程并未停止。

    上面的示例虽然停止了线程,但是如果for下面还有语句,还是会继续运行的。

    该如何解决语句继续运行的问题呢?

    package com.jvm.thread;

    public class MyThread04 extends Thread {

       @Override

       public void run() {

          try {

              for (int i = 0; i < 500000; i++) {

                 if (this.interrupted()) {

                    System.out.println("已经是停止状态,立即退出!");

                    throw new InterruptedException();

                 }

                 System.out.println("i = " + (i + 1));

              }

              System.out.println("for下面语句运行,线程并未停止。");

          } catch (InterruptedException e) {

              System.out.println("进入 MyThread04 类的 run() 的catch{}...");

              e.printStackTrace();

          }

       }

       public static void main(String[] args) {

          try {

              MyThread04 myThread04 = new MyThread04();

              myThread04.start();

              Thread.sleep(2000);

              myThread04.interrupt();

          } catch (InterruptedException e) {

              System.out.println("main catch{}...");

              e.printStackTrace();

          }

          System.out.println("main() end ....");

       }

    }

    i = 220112

    i = 220113

    main() end ....

    已经是停止状态,立即退出!

    进入 MyThread04 类的 run() 的catch{}...

    java.lang.InterruptedException

        at com.jvm.thread.MyThread04.run(MyThread04.java:10)

                              

    b、使用 return 停止线程

    interrupt() 与 return 结合使用

    package com.jvm.thread;

    public class MyThread05 extends Thread {

       @Override

       public void run() {

          while(true){

              if(this.isInterrupted()){

                 System.out.println("停止了!");

                 return;

              }

          }

       }

      

       public static void main(String[] args) throws InterruptedException {

          MyThread05 myThread05 = new MyThread05();

          myThread05.start();

          Thread.sleep(2000);

          myThread05.interrupt();

       }

    }

    10、怎么暂停线程?

    暂停线程意味着此线程还可以恢复运行。在java多线程中,可以使用suspend() 暂停线程,使用 resume() 恢复线程的执行。

    suspend 与 resume 方法的缺点——独占

    suspend 与 resume 方法的缺点——不同步

    11、线程的优先级

    在操作系统中,线程可以划分优先级,优先级较高的线程得到的CPU资源较多,也就是CPU优先执行优先极高的县城对象中的任务。

    设置线程优先级有助于帮组“线程规划器”确定下一次选择哪一个线程来优先执行。

    优先级具有随机性。

    12、守护线程

    在Java线程中有两种线程,一种是用户线程,另一种是守护线程。

    当进程中不存在非守护线程了,则守护线程自动销毁。典型的守护线程就是垃圾回收线程。

  • 相关阅读:
    Modbus: 1. Java使用Modbus读取Slave端数据(TCP)
    Nodejs后台发送https请求验证证书
    Cocos2d-JS: 2.编译到安卓和iOS
    Cocos2d-JS: 1.环境搭建
    [转载]聪明人为什么不统治世界——从围棋到德州扑克
    [转载] 国内外GIS方面的网站(较全)
    [转载]土豪算法(笑话也是实话)
    [转载]混沌理论三原则
    [转]追MM的各种算法
    [转载]建筑美和数学美
  • 原文地址:https://www.cnblogs.com/skorzeny/p/7073509.html
Copyright © 2011-2022 走看看