Java多线程

本文详细介绍了Java多线程的相关知识,包括多线程基础、创建新线程、线程状态、中断线程、守护线程、线程同步、死锁以及多种同步机制的使用,如wait、notify、ReentrantLock、Condition、ReadWriteLock和ThreadLocal等。通过实例展示了线程同步的重要性,以及如何避免死锁和高效地管理线程。
摘要由CSDN通过智能技术生成

Java多线程

多线程基础

操作系统:Windows、macOS、Linux

CPU执行代码都是一条一条顺序执行的,但是,即使是单核的CPU,也可以同时执行多任务。

例如,假设我们有语文、数学、英语3门作业要做,每个作业需要30分钟。我们把这3门作业看成是3个任务,可以做1分钟语文作业,再做1分钟数学作业,再做1分钟英语作业。

对于CPU来说,当某个线程获取了CPU时间片的时候,这个线程就会执行。

  • 进程

在计算机中,我们把一个任务称为一个进程,浏览器就是一个进程,视频播放器是另一个进程。

  • 线程

某些进程内部还需要同时执行多个子任务。例如,我们在使用Word时,Word可以让我们一边打字,一边进行拼写检查,同时还会实时保存。

  • 进程VS线程

一个进程可以包含一个或多个线程,但至少会有一个线程。

在这里插入图片描述

创建新线程

Java程序启动的时候,实际上是启动了一个JVM进程,然后,JVM启动主线程来执行main()方法,在main()方法中又可以启动其他线程。

创建并启动一个线程。需要实例化一个Thread实例,然后调用它的的start()方法。

public class MainTest{
   
    public static void main(String[] args){
   
        Thread t = new Thread();
        t.start();//启动新线程
    }
}

方法一: 继承Thread类,然后重写run()方法

public class MainTest{
   
    public static void main(String[] args){
   
        Thread t = new MyThread();
        t.start();
    }
    static class MyThread extends Thread{
   
        public void run(){
   
            sout("start new thread");
        }
    }
}

方法二: 实现Runnable接口,然后重写run()方法

public class MainTest{
   
    public static void main(String[] args){
   
        Thread t2 = new Thread(new MyRunnable());
        t2.start();
    }
    static class MyRunnable implements Runnable{
   

        @Override
        public void run() {
   
            System.out.println("myThread2启动!");
        }
    }
}

方法三: Java8引入了lambda表达式,可以进一步简写:

public class Main {
   
    public static void main(String[] args) {
   
        Thread t = new Thread(() -> {
   
            System.out.println("start new thread!");
        });
        t.start(); // 启动新线程
    }
}

其实,还有一个方法也可以:

//本方法类似于lambda表达式
Thread t4 = new Thread(){
   
            public void run(){
   
                System.out.println("t4线程启动!");
            }
        };
t4.start();

**线程休眠:**sleep()方法可以使得线程休眠。

public static native void sleep(long millis) throws InterruptedException;
Thread t3 = new Thread(()->{
   
            try {
   
                Thread.sleep(1000);//1000毫秒
            } catch (InterruptedException e) {
   
                System.out.println("Thread...end");
            }
            System.out.println("lambda表达式多线程!");
        });
        t3.start();
        try {
   
            Thread.sleep(10);//10毫秒
        } catch (InterruptedException e) {
   
            System.out.println("main...end");
        }

        Thread t4 = new Thread(){
   
            public void run(){
   
                System.out.println("t4线程启动!");
            }
        };
        t4.start();

结果是:t4线程启动!
lambda表达式多线程!

线程的状态

  • New:新创建的线程,尚未执行
  • Runnable:运行中的线程,正在执行run()方法
  • Blocked:运行中的线程,因为某些操作被阻塞而挂起
  • Waiting:运行中的线程,因为某些操作在等待;
  • Timed Waiting:运行中的线程,因为执行sleep()方法正在计时等待
  • Terminated:线程已终止,因为run()方法执行完毕

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YhBOXJIc-1622087125647)(Java多线程.assets/image-20210520190208751.png)]

线程启动后(start)可以在四个状态中切换,最后变成Terminated状态,线程终止。

线程终止的原因:

  1. 正常终止:run()方法执行到return语句。
  2. 意外终止:未捕获异常而终止。
  3. 强制终止:stop()方法(不建议)
public class Main {
   
    public static void main(String[] args) throws InterruptedException {
   
        Thread t1 = new Thread(() -> {
   
            try {
   
            	t2.sleep(10);//10毫秒
        	} catch (InterruptedException e) {
   
            	e.printStackTrace();
        	}
            System.out.println("t1启动");
        });
        Thread t2 = new Thread(() -> {
   
            try {
   
            	t2.sleep(1000);//10毫秒
        	} catch (InterruptedException e) {
   
            	e.printStackTrace();
        	}
            System.out.println("t2启动");
        });
        System.out.println("start");
        t1.start();
        t2.start();
        t2.join();
        
        t.join();//t线程加入后,其他线程会等待t结束后再启动。
        System.out.println("end");
    }
}

中断线程

如果线程需要执行一个长时间任务,就可能需要能中断线程。中断线程就是其他线程给该线程发一个信号,该线程收到信号后结束执行run()方法,使得自身线程能立刻结束运行。

public class Main {
   
    public static void main(String[] args) throws InterruptedException {
   
        Thread t = new MyThread();
        t.start();
        Thread.sleep(1); // 暂停1毫秒
        t.interrupt(); // 中断t线程
        t.join(); // 等待t线程结束
        System.out.println("end");
    }
}

class MyThread extends Thread {
   
    public void run() {
   
        int n = 0;
        while (! isInterrupted()) {
   
            n ++;
            System.out.println(n + " hello!");
        }
    }
}

sleep()方法是Thread类里面的,主要的意义就是让当前线程停止执行,让出cpu给其他的线程,但是不会释放对象锁资源以及监控的状态,当指定的时间到了之后又会自动恢复运行状态。

wait()方法是Object类里面的,主要的意义就是让线程放弃当前的对象的锁,进入等待此对象的等待锁定池,只有针对此对象调动notify方法后本线程才能够进入对象锁定池准备获取对象锁进入运行状态。

t.start()开启了新的线程,这个时候两个线程同时存在,maint线程谁获得cpu时间片的概率是相同的。这个时候main方法暂停1毫秒保证了cpu可以让t方法在中断前先执行从而输出1+“hello”。然后t线程中断,中断以后便不会再输出n+“hello”,这个时候,然后cpu给main方法执行join再让t方法完全运行完,或者给到t方法直接运行完,最后就输出end

三线程的Interrupt

public class Main {
   
    public static void main(String[] args) throws InterruptedException {
   
        Thread t = new MyThread();
        t.start();
        Thread.sleep(1000);
        t.interrupt(); // 中断t线程
        t.join(); // 等待t线程结束
        System.out.println("end");
    }
}

class MyThread extends Thread {
   
    public void run() {
   
        Thread hello = new HelloThread();
        hello.start(); // 启动hello线程
        try {
   
            hello.join(); // 等待hello线程结束
        } catch (InterruptedException e) {
   
            System.out.println("interrupted!");
        }
        hello.interrupt()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值