JAVA多线程

多线程

1. 多线程实现

1.1 继承Thread类

  • 继承Thread类

  • 重写run方法

  • 创建实例

  • 启动线程 start()

  • 先创建一个线程类,然后在另一个类中,创建该对象,然后run即可

  • getName()可以获取线程名称

  • setName()可以设置线程名称
    在这里插入图片描述

在这里插入图片描述


public class Demo01 {
    public static void main(String[] args) {
        MyThread1 t1 = new MyThread1();
        MyThread2 t2 = new MyThread2();
        t1.start();
        t2.start();
        
    }
}


class MyThread1 extends Thread{
    @Override
    public void run() {
        int i = 0;
        for (i = 0; i<=1000; i++){
            System.out.println(getName()+i);
        }
    }
}

class MyThread2 extends Thread{
    @Override
    public void run() {
        int i = 0;
        for (i = 0; i<=1000; i++){
            System.out.println(getName()+i);
        }
    }
}
  • 也可以使用有参构造方法直接设置线程名称,但是要重写有参构造方法。
  • MyThread t1 = new MyThread(“thread 01”)

在这里插入图片描述

  • Thread.currentThread().getName();可以获取当前线程的名字(比如main函数的)

1.2 实现Runnable接口

在这里插入图片描述

public class Demo02 {
    public static void main(String[] args) {
        // new Thread(new Myrunnable()).start();
        // new Thread(new Myrunnable()).start();
        
        Myrunnable m = new Myrunnable();
        Thread t1 = new Thread(m);
        Thread t2 = new Thread(m);
        t1.start();
        t2.start();
    }
}

class Myrunnable implements Runnable{
    @Override
    public void run() {
        for (int i=0;i<=1000;i++){
            System.out.println(Thread.currentThread().getName()+"---"+i);
        }
    }
}

在这里插入图片描述

1.3 线程池搭配Callable泛型接口(返回值也是泛型)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.4 匿名内部类实现

在这里插入图片描述

  • 下面的同时又Thread子类和Runnable接口,最后只会执行world线程,多次覆盖只最后一次有效
    在这里插入图片描述

2. 线程调度和控制

2.1 调度

  • getPriority获取线程优先级,默认5,最大10,最小1
  • 由于线程调度随机性,不是每一次都是高优先级先于低优先级运行,多次运行满足概率 高>低。

在这里插入图片描述

		MyThread1 t1 = new MyThread1();
        MyThread2 t2 = new MyThread2();
        t1.start();
        t2.start();
        System.out.println(t1.getPriority());

在这里插入图片描述

2.2 控制

  • sleep线程休眠,单位毫秒,1s=1000ms;静态方法Thread.sleep(1000)

  • join,等待该线程结束在执行其他线程。实例方法。

  • yield,线程手动切换,Thread.yield(),让多个线程更加和谐,但是不能保证每个线程一个运行一次,还是有几率随机调度。
    在这里插入图片描述

  • 守护线程,设置守护线程后,如果主线程结束,那么守护线程将不会继续执行。就像老家没了,坦克就输了。

  • 在JVM中,所有非守护线程都执行完毕后,无论有没有守护线程,虚拟机都会自动退出。因此,JVM退出时,不必关心守护线程是否已结束。

  • 参考
    在这里插入图片描述

在这里插入图片描述


3. 线程生命周期

在这里插入图片描述

在这里插入图片描述


4. 线程同步

  • 解决多线程读写同一变量

在这里插入图片描述

  • 像下面这样,每次创建的锁对象就不会是一个了,所以才能成功锁住。
    在这里插入图片描述

在这里插入图片描述

4.2 同步方法

  • 同步方法的锁对象就是this,自身对象
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

4.3 线程安全的集合类

  • Collection的静态方法,直接返回一个线程安全集合对象。
    在这里插入图片描述

4.4 Lock

在这里插入图片描述

在这里插入图片描述


5. 死锁

在这里插入图片描述

在这里插入图片描述

5.2 代码示例


public class Demo04 {
    public static void main(String[] args) {
        DeadLock d1 = new DeadLock(true);
        DeadLock d2 = new DeadLock(false);
        d1.start();
        d2.start();
    }
}

class DeadLock extends Thread {
    private boolean flag;
    public DeadLock(boolean flag){
        this.flag = flag;
    }
    
    // 下面代码,如果thread0获取锁a,打印if obja,然后系统调度thread1,thread1获取锁b,打印else objb
    // 然后系统再次切换回thread0,此时thread0想要获取锁b,但是此时锁b还没有释放,就会形成死锁
    @Override
    public void run() {
        if (flag){
            synchronized (MyLock.obja){
                System.out.println("if obja");
                synchronized (MyLock.objb){
                    System.out.println("if objb");
                }
            }
        }else {
            synchronized (MyLock.objb){
                System.out.println("else objb");
                synchronized (MyLock.obja){
                    System.out.println("else obja");
                }
            }
        }
    }
}

class MyLock{
    // 定义2把锁,给synchronized作为参数锁
    public static final Object obja = new Object();
    public static final Object objb = new Object();
}


6. 线程间通信

6.1 等待唤醒

在这里插入图片描述

在这里插入图片描述


7. 线程组

  • 默认主线程组

在这里插入图片描述


8. 线程池

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


8. 定时器使用

import java.util.Timer;
import java.util.TimerTask;

public class Demo06 {
    public static void main(String[] args) {
        Timer t = new Timer();
        // 3秒后开始执行,然后每隔2秒钟,调度一次
        t.schedule(new MyTimerTask(), 3000, 2000);
    }
}

class MyTimerTask extends TimerTask{
    @Override
    public void run() {
        System.out.println("beng beng");
    }
}


9. 常见面试题

9.1 多线程几种实现方案

  • 继承Thread类
  • 实现Runnable接口
  • 泛型接口Callable搭配线程池

9.2 同步几种方式

  • 同步代码块 synchronized
  • 同步方法

9.3 线程run和start方法区别

  • run就是普通函数调用
  • start,jvm开启一个新线程,然后调用run方法

9.4 sleep和wait区别

  • sleep必须指定时间,不释放锁(Thread.sleep() )
  • wait可以也可以不指定时间,自动释放锁( Object.wait() )

9.5 为什么wait(),notify(),notifyAll()都定义在Object类中

  • 因为这些方法调用依赖锁对象,而同步代码块的锁对象是任意锁。Object代表任意锁。

9.6 线程状态和生命周期

  • 参考前面章节!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值