zoukankan      html  css  js  c++  java
  • java 线程 总结

    1.前言

    (1)线程的上一级是进程,进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。
    (2)线程与进程相似,但线程是一个比进程更小的执行单位,也被称为轻量级进程。一个进程在其执行的过程中可以产生多个线程。
    (3)多线程就是多个线程同时运行或交替运行。
    (4)提倡多线程而不是多进程 的原因是 线程间的切换和调度的成本远远小于进程。
    (5)自定义线程可以继承Thread类 ,或者 实现Runnable接口 。
    (6)多进程共享数据导致脏数据,可以使用同步锁 synchronized 解决。
    (7)使用 interrupt() 和 return 配合 停止线程。
    (8)不是优先级低的线程就一定在优先级高的线程后面运行,而是运行的机率会低一些,,反之亦然。
    (9)线程分为用户线程和守护线程 ,当 用户线程 结束后,守护线程跟着结束 ,对于自定义线程可使用方法 setDaemon(true); 设置该线程为守护线程 。
      常见的 守护线程是 垃圾回收线程
    (10)开启线程的方式一共三种:Thread类、Runnable接口、callable接口

    2.自定义线程

    package com.example.javabaisc.myThread;
    
    import org.junit.jupiter.api.Test;
    
    public class T1 {
    
        @Test
        public void t1(){
            //调用方法一
    //        Mythread m = new Mythread();
    //        m.start();
    
    
            //调用方法二
            MyRunnable mr = new MyRunnable();
            Thread thread=new Thread(mr);
            thread.start();
            System.out.println("结束");
    
    
        }
    
    
    }
    
    //方法一:
    class Mythread extends Thread {
        @Override
        public void run(){
            super.run();
            System.out.println("我的线程");
    
        }
    
    }
    
    //方法二:
    class MyRunnable implements Runnable{
    
        @Override
        public void run() {
            System.out.println("使用接口实现我的线程");
        }
    }
    View Code

    3.多个线程之间不共享变量线程安全的情况

    每个线程都有自己的实例变量count ,互不影响
    package com.example.javabaisc.myThread;
    
    import org.junit.jupiter.api.Test;
    
    /**
     * 多个线程之间不共享变量线程安全的情况
     */
    public class T2 {
    
        @Test
        public void t2(){
            MyThread2 m1 = new MyThread2("1");
            MyThread2 m2 = new MyThread2("2");
            MyThread2 m3 = new MyThread2("3");
            m1.start();
            m2.start();
            m3.start();
    
        }
    
    }
    
    class MyThread2 extends Thread {
        private int count = 5;
    
        MyThread2(String name) {
    //        super();
            //给父类的name属性赋值
            this.setName(name);
        }
    
        //每次new MyThread2只会执行一次run();
        @Override
        public void run() {
            super.run();
            while (count>0){
                System.out.println("由 线程 " + MyThread2.currentThread().getName() + " 计算,剩余count=" + count);
                count--;
            }
        }
    }
    
    /*
    由 线程 1 计算,剩余count=5
    由 线程 1 计算,剩余count=4
    由 线程 1 计算,剩余count=3
    由 线程 1 计算,剩余count=2
    由 线程 1 计算,剩余count=1
    由 线程 3 计算,剩余count=5
    由 线程 2 计算,剩余count=5
    由 线程 3 计算,剩余count=4
    由 线程 3 计算,剩余count=3
    由 线程 3 计算,剩余count=2
    由 线程 3 计算,剩余count=1
    由 线程 2 计算,剩余count=4
    由 线程 2 计算,剩余count=3
    由 线程 2 计算,剩余count=2
    由 线程 2 计算,剩余count=1
     */
    
    /*
    每个线程都有自己的实例变量count ,互不影响
     */
    View Code

    4.共享数据的情况 [使用 同步锁 可解决脏数据问题]

    package com.example.javabaisc.myThread;
    
    import org.junit.jupiter.api.Test;
    
    /**
     * 共享数据的情况 [使用 同步锁 可解决脏数据问题]
     */
    public class T3 {
        @Test
        public void t3() {
            MyThread3 myThread3 = new MyThread3();
            //参数分别是 自定义线程 ,线程名字
            Thread m1 = new Thread(myThread3, "1");
            Thread m2 = new Thread(myThread3, "2");
            Thread m3 = new Thread(myThread3, "3");
            Thread m4 = new Thread(myThread3, "4");
            Thread m5 = new Thread(myThread3, "5");
            m1.start();
            m2.start();
            m3.start();
            m4.start();
            m5.start();
    
        }
    }
    
    //class  MyThread3 extends Thread {
    //    //公共数据
    //    private int count = 5;
    //    //每次new MyThread3只会执行一次run();
    //    @Override
    //    public  void run() {
    //        super.run();
    //        int yu = count--;
    //        System.out.println("由 线程 " + MyThread3.currentThread().getName() + " 计算,剩余count=" + yu);
    //
    //    }
    //}
    
    /*
    由 线程 3 计算,剩余count=2
    由 线程 5 计算,剩余count=3
    由 线程 1 计算,剩余count=5
    由 线程 4 计算,剩余count=1
    由 线程 2 计算,剩余count=4
     */
    
    /*
    本应该剩余count是依次递减的 ,可是显示是乱数据,
    因为在大多数jvm中,count–-的操作分为如下三步:
    取得原有count值
    计算 -1 的结果
    进行赋值
    并发线程获取count的值显然是无法避免脏数据
    
     */
    
    //使用锁 synchronized,即可解决线程脏数据
    class  MyThread3 extends Thread {
        //公共数据
        private int count = 5;
        //每次new MyThread3只会执行一次run();
        //添加了同步锁 synchronized
        @Override
        public synchronized void run() {
            super.run();
            int yu = count--;
            System.out.println("由 线程 " + MyThread3.currentThread().getName() + " 计算,剩余count=" + yu);
    
        }
    }
    /*
    由 线程 1 计算,剩余count=5
    由 线程 5 计算,剩余count=4
    由 线程 4 计算,剩余count=3
    由 线程 3 计算,剩余count=2
    由 线程 2 计算,剩余count=1
     */
    View Code

    5.使用 interrupt() 和 return 配合 停止线程

    package com.example.javabaisc.myThread;
    
    import org.junit.jupiter.api.Test;
    
    /**
     * 使用 interrupt() 和 return 配合 停止线程
     */
    
    public class T4 {
    
    
        @Test
        public void t() throws InterruptedException {
            MyThread4 m = new MyThread4();
            m.start();
            //主线程休眠0.01秒后执行
            Thread.sleep(10);
            m.interrupt();
            Thread.sleep(1000);
            System.out.println("停了么?");
    
        }
    
    }
    
    class MyThread4 extends Thread {
    
        //每次new MyThread4只会执行一次run();
        @Override
        public  void run() {
            super.run();
            int i = 0;
            while (true) {
                //判断该线程是否被执行了interrupt()
                if (this.isInterrupted()) {
                    System.out.println("线程被停止");
                    return;
                }
                System.out.println(i++);
            }
    
        }
    }
    View Code

    打印结果:

     6.线程优先级对比

    setPriority不一定起作用的,在不同的操作系统不同的jvm上,效果也可能不同
    数字越大优先级越高,但不是优先级低就一定在优先级高的线程后面运行,而是运行的机率会低一些,,反之亦然。
    package com.example.javabaisc.myThread;
    
    import org.junit.jupiter.api.Test;
    
    /**
     * 线程优先级对比
     * setPriority不一定起作用的,在不同的操作系统不同的jvm上,效果也可能不同
     * 数字越大优先级越高,但不是优先级低就一定在优先级高的线程后面运行,而是运行的机率会低一些,,反之亦然。
     *
     */
    public class T5 {
        @Test
        public void t() {
            MyThread5 a = new MyThread5("A");
            MyThread5 b = new MyThread5("B");
    //        a.setPriority(10);
    //        b.setPriority(1);
            a.setPriority(1);
            b.setPriority(10);
            a.start();
            b.start();
    
        }
    
    }
    
    class MyThread5 extends Thread {
    
        MyThread5(String name) {
            super();
            this.setName(name);
        }
    
        @Override
        public  void run() {
            super.run();
            System.out.println("我是线程:" + Thread.currentThread().getName());
        }
    }
    View Code

     7.守护线程 ,当 用户线程 结束后,守护线程跟着结束 

    注意:

    不可使用@Test测试 ,否则所有线程都会随着用户线程结束而结束,看不到非守护线程运行效果
    package com.example.javabaisc.myThread;
    
    import org.junit.jupiter.api.Test;
    
    /**
     * 守护线程 ,当 用户线程 结束后,守护线程跟着结束
     *
     * 不可使用@Test测试 ,否则所有线程都会随着用户线程结束而结束,看不到非守护线程运行效果
     *
     *
     */
    public class T6 {
    
    public static void main(String[] args) throws InterruptedException {
            MyThread6 a = new MyThread6();
            //设置该线程为守护线程
            a.setDaemon(true);
            a.start();
            Thread.sleep(1000);
            System.out.println("用户线程结束,退出,守护线程也跟着退出");
    
    
        }
    }
    
    
    class MyThread6 extends Thread {
        private int i = 0;
    
        @Override
        public void run() {
            while (true) {
                System.out.println(i++);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
    
            }
    
        }
    }
    View Code

    不设为守护线程的打印结果

     设为守护线程的打印结果

     

  • 相关阅读:
    Python字符串转码问题
    tcpip详解笔记(21) TCP的路径MTU探测与长肥管道
    sync,fsync,fdatasync,fflush
    tcpip详解笔记(22) telnet协议
    tcpip详解笔记(18)TCP的超时与重传
    tcpip详解笔记(16) TCP的交互数据流
    Get exception description and stack trace which caused an exception
    tcpip详解笔记(20) TCP的Keepalive定时器
    [转]应该知道的Linux技巧
    How to prettyprint JSON script?
  • 原文地址:https://www.cnblogs.com/c2g5201314/p/13099997.html
Copyright © 2011-2022 走看看