Java多线程复习笔记 传智播客java教程

本文详细介绍了Java中的多线程概念,包括线程的创建、命名、优先级、调度、休眠、加入、礼让、守护、中断等。通过实例展示了通过继承Thread类和实现Runnable接口两种方式创建线程,以及线程同步、Lock接口的使用来解决线程安全问题。此外,还讨论了线程组、线程池的优势和使用,以及Callable接口实现带返回值的多线程。并提及了死锁问题、定时器和多任务执行。
摘要由CSDN通过智能技术生成

多线程的概述

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

多线程实现 1

在这里插入图片描述

通过重写run方法来使用多线程,多线程里面代码一般都是比较耗时的

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

在这里插入图片描述

如果要使用多线程就需要通过start方法 使线程执行,因为run方法是仅仅是封装被线程执行的代码。

在这里插入图片描述

        fbb s1 = new fbb();
        s1.start();
        //Exception in thread "main" java.lang.IllegalThreadStateException
        //同一个线程只能调用一次没办法调用两次
        fbb s2 = new fbb();
        //可以通过创建两个对象来调用两个线程
        
        s2.start();

获取线程的名字与修改

  @Override
    public void run() {

        for (int i=0;i<1000;i++){
            System.out.println(i+" "+getName());
        }
    }

在这里插入图片描述

 fbb s1 = new fbb();
        s1.setName("线程1");
        s1.start();

        fbb s2 = new fbb();
        //修改名字
        s2.setName("线程2");


        s2.start();

或者是通过他的构造方法进行改名
在这里插入图片描述

获取当前线程的线程名字

在这里插入图片描述

线程调度 优先级

在这里插入图片描述
在这里插入图片描述
优先级默认是5

线程休眠

在这里插入图片描述

public class fbb extends Thread {
    @Override
    public void run() {

        for (int i=0;i<1000;i++){
            System.out.println(i+" "+getName());
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

线程的加入

在这里插入图片描述
在这里插入图片描述
只有调用join的线程执行完毕后,后面的线程才会开始执行

礼让线程

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

public class fbb extends Thread {
    @Override
    public void run() {

        for (int i=0;i<1000;i++){
            System.out.println(i+" "+getName());
            Thread.yield();

        }
    }
}

守护线程

在这里插入图片描述

在这里插入图片描述

当非守护线程停止,守护线程才停止.

中断线程

在这里插入图片描述
stop过时了不建议使用
在这里插入图片描述
public void interrupt(): 中断线程,并抛出InterruptedException,程序正常结束

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

多线程实现2 Runnable接口

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

在这里插入图片描述

在这里插入图片描述

public class fbb implements Runnable {
    @Override
    public void run() {

        for (int i=0;i<10000;i++){

            System.out.println(i+" "+Thread.currentThread().getName());//currentThread()方法返回正在被执行的线程的信息。

        }
    }
}
public class Main {
    public static void main(String[] args) throws InterruptedException {
        fbb s1 = new fbb();
        Thread t1 = new Thread(s1,"线程1");
        Thread t2 = new Thread(s1,"线程2");
        t1.start();
        t2.start();
    }
}

两个多线程实现方法的区别图解

如何解决线程安全问题

在这里插入图片描述
在这里插入图片描述
问题例子卖票

public class fbb implements Runnable {
    private  static int     tick=100;
    @Override
    public void run() {

           while (true) {
               if (tick>0){
               try {
                   Thread.sleep(100);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
                   System.out.println(Thread.currentThread().getName()+" "+(tick--)+"票");
           }

            }
        }


    }

public class Main {
    public static void main(String[] args) throws InterruptedException {
        fbb s1 = new fbb();
        Thread t1 = new Thread(s1,"窗口1");
        Thread t2 = new Thread(s1,"窗口2");
        Thread t3 = new Thread(s1,"窗口3");
        t1.start();
        t2.start();

        t3.start();
    }
}

解决线程问题的实现1 同步代码

在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/8a92e596cb534c4a89c26c1e1e219e4d.png
在这里插入图片描述

public class fbb implements Runnable {
    private   int     tick=1000;
    private Object obj = new Object();
    @Override
    public void run() {

           while (true) {
               synchronized (obj){//使用同步代码块把他们给包起来
                   if (tick>0){
                       try {
                           Thread.sleep(100);
                       } catch (InterruptedException e) {
                           e.printStackTrace();
                       }
                       System.out.println(Thread.currentThread().getName()+" "+(tick--)+"票");
                   }else {
                       return;
                   }
               }


            }
        }


    }

在这里插入图片描述

解决线程问题的实现2 接口Lock

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

package com.atguigu.com;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class fbb implements Runnable {
    private   int     tick=50;
    private Lock lock = new ReentrantLock();//ReentrantLock是Lock的实现类

    @Override
    public void run() {

           while (true) {
    //在这加上锁
               try {
                   //加锁
                   lock.lock();
                   if (tick > 0) {
                       try {
                           Thread.sleep(100);
                       } catch (InterruptedException e) {
                           e.printStackTrace();
                       }
                       System.out.println(Thread.currentThread().getName() + " " + (tick--) + "票");
                   } else {
                       return;
                   }
               }finally {
                   //释放锁
                   lock.unlock();
               }


            }
        }


    }


在这里插入图片描述

同步的好处和弊端

在这里插入图片描述
在这里插入图片描述
同步代码还可以放在方法上
同步方法就是this因为每个方法内都有一个隐藏的this对象
在这里插入图片描述

可以用class创建对象但是要是当前的class文件

让一个集合变成线程安全的集合

在这里插入图片描述

死锁问题

在这里插入图片描述
在这里插入图片描述
理想状态
在这里插入图片描述
不理想状态
在这里插入图片描述
问题代码分析
在这里插入图片描述

因为他们两个对象都进入到了synchronized 的"门"中 然后在进入下一个synchronized的"门"时无法访问 导致成为了死锁。

等待唤醒

在这里插入图片描述

 @Override
    public void run() {
        while (true){
            synchronized ( s){
                if (!s.falg){//如果不是空也就是修改完成数据了让他输出
                    try {
                        s.wait();//他醒了的时候也是从这里开始的
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(s.age+" "+s.name);
                s.falg=false;
                s.notify();
            }

        }
    }
 @Override
    public void run() {
    while (true){
        synchronized (s){
            if(s.falg){
                try {
                    s.wait();//如果是true让他进行等待
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        if(x%2==0){
            s.age=13;
            s.name="林超贤";
        }else {
            s.age=133;
            s.name="林超1贤";
        }
        x++;
        s.falg=true;//修改完成了就可以让他去输出访问
        s.notify();//唤醒
        }
    }


多线程的抓换图和运行情况

在这里插入图片描述

线程组的概述和使用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
线程的默认情况的Main组

修改线程所在的组


        Student s =new Student();
        Studendemo s1 = new Studendemo(s);
        SetSteb s2 = new SetSteb(s);
        ThreadGroup g1 = new ThreadGroup("彭于晏的线程组");//创建一共组
        Thread t1 = new Thread(g1,s1,"吴亦凡");//把他们分到新建的组里面
        Thread t2 = new Thread(g1,s1,"彭于晏");
        System.out.println(t1.getThreadGroup().getName());

线程组的好处

在这里插入图片描述

可以通过组名称设置后台线程,表示该组的线程都是后台线程守护线程

线程池

能够极大的保证线程的效率
用完线程后还可以回收。
在这里插入图片描述
用Executors产生线程池

线程池的好处

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

package com.company;

import com.sun.org.apache.bcel.internal.generic.FSUB;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {

    public static void main(String[] args) {
	    //创建一个线程池对象 控制要创建几个线程
        ExecutorService pool = Executors.newFixedThreadPool(2);
        //创建可执行Runnable或者Callable对象
        pool.submit(new Runnable());
        pool.submit(new Runnable());
    }
}

如果想要关闭线程不让他回收

     pool.submit(new Runnable());
        pool.shutdown();//停止

多线程实现3 Callable

Callable 是一个带泛形的接口
//这里指的泛形其实是指call的返回值

public class CallableTEX implements Callable {
    @Override
    public Object call() throws Exception {
        System.out.println("范冰冰"+""+Thread.currentThread().getName());
        return null;
    }
}

在通过线程池进行调用,但是他依赖线程池调用,如果需要用返回值的案例的话可以用线程3.

在这里插入图片描述

多线程方式实现求和

在这里插入图片描述
用此方法获取返回值

public class Runnable implements Callable {
    private int number;
    public Runnable(int number){
        this.number=number;
    }
    @Override
    public Object call() throws Exception {
        int sum=0;
        for (int x=1;x<=number;x++){
            sum+=x;
        }
        return sum;
    }
}
	    //创建一个线程池对象 控制要创建几个线程
        ExecutorService pool = Executors.newFixedThreadPool(2);
        //创建可执行Runnable或者Callable对象

         Future<Integer>fu = pool.submit(new Runnable(100));
        Integer i1 = fu.get();
        System.out.println(i1);
        pool.shutdown();

定时器

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
使用结束任务优化
在这里插入图片描述

多任务

在这里插入图片描述

连环爆炸,后面的2000就是前面3000执行后每隔2秒执行一次

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值