• 多线程(一)初识多线程


    一.环境

      idea

    二.为什么使用多线程

    俗话说:众人拾柴火焰高。为什么不让一个人去拾柴呢!!!当然是团结啦!!但是最总要的是提高效率

    所以在程序中也是一样,你可以讲一个线程看做一个人,为了加快程序效率就出现了多线程。

     三.什么是线程

    面试题:线程和进程的区别是什么

    答:线程是程序的一条运行途径,进程是一个线程集合

    四.创建线程的方式

    多线程执行我们默认忽略极小误差默认是同时执行的,关于谁先执行就看谁能先强到CPU的执行权

    4.1实现Thread类

    public class ThreadTest extends Thread {
    
        //重写Thread类型的run方法
        @Override
        public void run() {
            System.out.println("子线程运行-------");
            //线程执行的逻辑代码
            for(int i=0;i<20;i++){
                System.out.println(getName()+"i:"+i);
            }
            System.out.println("线程结束");
        }
    
    
    }

    创建测试类

    public static void main(String[] args) {
            ThreadTest threadTest=new ThreadTest();//创建线程
            threadTest.start();//启动线程
    
            for(int i=0;i<20;i++){
                System.out.println(Thread.currentThread().getName()+"i:"+i);//主线程需要运行的代码
            }
        }

    为什么不使用thread.run()方法启动多线程:由于我们创建线程和普通的new对象一样当使用run方法就相当于调用方法,而不是启动多线程了

    4.2继承Runnable接口

    public class ThreadTest implements Runnable {
        //重写Thread类型的run方法
    
        public void run() {
            System.out.println("子线程运行-------");
            //线程执行的逻辑代码
            for(int i=0;i<20;i++){
                System.out.println(Thread.currentThread().getName()+"i:"+i);
            }
            System.out.println("线程结束");
        }
    
    
    }

    创建测试类

     public static void main(String[] args) {
            ThreadTest threadTest=new ThreadTest();//创建线程
            Thread thread=new Thread(threadTest);
            thread.start();//启动线程
    
            for(int i=0;i<20;i++){
                System.out.println(Thread.currentThread().getName()+"i:"+i);//主线程需要运行的代码
            }
        }

    拿这种方式和上一中来比较,可以看出来两种方式创建线程的方式不同

    面试题:通常创建线程是使用继承Thred类好还是实现Runnable接口好

    答:实现Runnable接口好,因为Java只支持单继承,但是支持多实现

    4.3使用匿名内部类的方式创建多线程

     public static void main(String[] args) {
            Thread thread=new Thread(new Runnable() {//匿名内部类
                public void run() {//业务逻辑代码
                    for (int i=0;i<20;i++){
                        System.out.println(Thread.currentThread().getName()+"子线程i:"+i);
                    }
                }
            });
            thread.start();
            for (int i=0;i<20;i++){//主线程逻辑代码处
                System.out.println(Thread.currentThread().getName()+"i:"+i);
            }
        }

    4.4多线程常用API

    常用线程api方法

    start()

    启动线程

    currentThread()

    获取当前线程对象

    getID()

    获取当前线程ID      Thread-编号  该编号从0开始

    getName()

    获取当前线程名称

    sleep(long mill)

    休眠线程

    Stop()

    停止线程,

    常用线程构造函数

    Thread()

    分配一个新的 Thread 对象

    ThreadString name

    分配一个新的 Thread对象,具有指定的 name正如其名

    ThreadRunable r

    分配一个新的 Thread对象

    ThreadRunable r, String name

    分配一个新的 Thread对象

    五.多线程的几种状态的相互转换

     

    5.1新建状态

       当用new操作符创建一个线程时, 例如new Thread(r),线程还没有开始运行,此时线程处在新建状态。 当一个线程处于新生状态时,程序还没有开始运行线程中的代码

    5.2就绪状态

    一个新创建的线程并不自动开始运行,要执行线程,必须调用线程的start()方法。当线程对象调用start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行run()方法。当start()方法返回后,线程就处于就绪状态。

         处于就绪状态的线程并不一定立即运行run()方法,线程还必须同其他线程竞争CPU时间,只有获得CPU时间才可以运行线程。因为在单CPU的计算机系统中,不可能同时运行多个线程,一个时刻仅有一个线程处于运行状态。因此此时可能有多个线程处于就绪状态。对多个处于就绪状态的线程是由Java运行时系统的线程调度程序(thread scheduler)来调度的。

    5.3运行状态

    当线程获得CPU时间后,它才进入运行状态,真正开始执行run()方法.

    5.4阻塞状态

        线程运行过程中,可能由于各种原因进入阻塞状态:
            1>线程通过调用sleep方法进入睡眠状态;
            2>线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;
            3>线程试图得到一个锁,而该锁正被其他线程持有;
            4>线程在等待某个触发条件;

    5.5死亡状态

    有两个原因会导致线程死亡:
      1) run方法正常退出而自然死亡,
       2) 一个未捕获的异常终止了run方法而使线程猝死。
      为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法。如果是可运行或被阻塞,这个方法返回true; 如果线程仍旧是new状态且不是可运行的, 或者线程死亡了,则返回false.

    六.join()方法的作用

    调用那个线程的join()方法就是,需要当那个线程执行完后再执行当前线程

    例如:

     public static void main(String[] args) {
            final Thread thread1=new Thread(new Runnable() {//匿名内部类
                public void run() {//业务逻辑代码
                    for (int i=0;i<20;i++){
                        System.out.println(Thread.currentThread().getName()+"子线程i:"+i);
                    }
                }
            });
            Thread thread2=new Thread(new Runnable() {//匿名内部类
    
                public void run() {//业务逻辑代码
                    try {
                        thread1.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    for (int i=0;i<20;i++){
                        System.out.println(Thread.currentThread().getName()+"子线程i:"+i);
                    }
                }
            });
            thread2.start();
            thread1.start();
    
    
        }

    结果:不加thread1.join()

    加入thread1.join()

  • 相关阅读:
    const,var,let区别(转载)
    在windows上搭建redis集群
    Linux学习笔记—vim程序编辑器
    Linux学习笔记—文件与文件系统的压缩与打包(转载)
    Linux学习笔记—Linux磁盘与文件系统管理(转载)
    五,mysql优化——sql语句优化小技巧
    八,mysql优化——读写分离
    六,mysql优化——小知识点
    七,mysql优化——表的垂直划分和水平划分
    三,mysql优化--sql语句优化之索引一
  • 原文地址:https://www.cnblogs.com/wy0119/p/8998976.html
Copyright © 2020-2023  润新知