zoukankan      html  css  js  c++  java
  • 多线程(一)初识多线程

    一.环境

      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()

  • 相关阅读:
    OSX安装nginx和rtmp模块(rtmp直播服务器搭建)
    用runtime来重写Coder和deCode方法 归档解档的时候使用
    Homebrew安装卸载
    Cannot create a new pixel buffer adaptor with an asset writer input that has already started writing'
    OSX下面用ffmpeg抓取桌面以及摄像头推流进行直播
    让nginx支持HLS
    iOS 字典转json字符串
    iOS 七牛多张图片上传
    iOS9UICollectionView自定义布局modifying attributes returned by UICollectionViewFlowLayout without copying them
    Xcode6 iOS7模拟器和Xcode7 iOS8模拟器离线下载
  • 原文地址:https://www.cnblogs.com/wy0119/p/8998976.html
Copyright © 2011-2022 走看看