前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java多线程与并发

Java多线程与并发

作者头像
瑞新
发布2022-05-11 16:12:35
4490
发布2022-05-11 16:12:35
举报

文章目录

线程和进程的区别

JDK选择长期版本

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

线程和进程的区别

基础

线程进程、内核态用户态转换,为何转换、系统中断、内核态的多线程是如何通过轻量级实现的。结合自己理解融入到Java线程中

由来

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

区别

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

寄存器可被存储线程的局部变量,但是不能其他线程的相关变量

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

关系

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

代码查看主线程

Java采用单线程编程模型,

package thread;

/**
 * @Author bennyrhys
 * @Date 2020-03-26 21:50
 */
public class CurrentThreadDemo {
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName());
    }
}

thread.CurrentThreadDemo main

Thread中的start方法和run方法的区别

效果图

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

代码

package thread;

/**
 * @Author bennyrhys
 * @Date 2020-03-26 22:17
 */
public class ThreadTest {
    public static void attack() {
        System.out.println("Fight");
        System.out.println("attack is :"+ Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        Thread t = new Thread(){
            @Override
            public void run() {
                attack();
            }
        };
        System.out.println(Thread.currentThread().getName()); // main
//        t.run();  // main
        t.start(); // attack is :Thread-0
    }
}

main Fight attack is :Thread-0

分析源码

新线程由start创建

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

创建一个新的线程

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

创建一个线程去run方法名称

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

没有可比性run和star

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

Thread和Runnable是什么关系

本质

Thread类 Runnable接口

Runnable只有一个run抽象方法,说明此接口并不具备多线程的特性. 是依赖Thread里面的star方法在去调用run方法实现多线程

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

源码

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

代码演示

普通Thread.start()线程-效果图

多线程同时遍历

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

MyThread

package thread;

/**
 * 继承线程
 * @Author bennyrhys
 * @Date 2020-03-27 18:53
 */
public class MyThread extends Thread{
    private String name;

    public MyThread(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("This is "+i+" Thread:" + this.name);
        }
    }
}
package thread;

/**
 * @Author bennyrhys
 * @Date 2020-03-27 18:56
 */
public class MyThreadMain {
    public static void main(String[] args) {
        new MyThread("THREAD1").start();
        new MyThread("THREAD2").start();
        new MyThread("THREAD3").start();
    }
}

通过Thread类启动Runnable多线程-效果图

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

MyRunnalbe

package thread;

/**
 * @Author bennyrhys
 * @Date 2020-03-27 19:20
 */
public class MyRunnalbe implements Runnable{
    private String name;

    public MyRunnalbe(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("This is "+i+" Thread:" + this.name);
        }
    }
}

MyRunnableMain

package thread;

/**
 * @Author bennyrhys
 * @Date 2020-03-27 19:21
 */
public class MyRunnableMain {
    public static void main(String[] args) {
        // 通过Thread的start()方法实现Runable的多线程
        MyRunnalbe thread1 = new MyRunnalbe("Thread1");
        Thread t1 = new Thread(thread1);
        t1.start();
        MyRunnalbe thread2 = new MyRunnalbe("Thread2");
        Thread t2 = new Thread(thread2);
        t2.start();
        MyRunnalbe thread3 = new MyRunnalbe("Thread3");
        Thread t3 = new Thread(thread3);
        t3.start();
    }
}

如何实现处理线程的返回值

如何给run()方法传参

跟线程相关的业务逻辑放在run()方法,但是run()方法没有参数也没有返回值的。 主要三种: 构造函数传参(上边用过) 成员变量传参(setName) 回调函数传参

实现的方式主要有三种

在这里插入图片描述

主线程等待法

自己实现循环等待逻辑,需要循环等待的多,代码变得臃肿 循环多久不确定,无法精准控制

CycleWait
package thread;

/**
 * @Author bennyrhys
 * @Date 2020-03-27 20:49
 */
public class CycleWait implements Runnable{

    private String value;

    @Override
    public void run() {
        try {
            Thread.sleep(3000);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        value = "we have data now";
    }


    public static void main(String[] args) throws InterruptedException {
        CycleWait cw = new CycleWait();
        Thread t = new Thread(cw);
        t.start();

        // 主线程等待法
        while (cw.value == null) {
            Thread.sleep(100);
        }

        // 未加等待法 null, 加了等待法 we have data now
        System.out.println(cw.value);

    }
}

Thread类join()方法阻塞当前线程,等待当前子线程执行完毕

比主线程等待法实现更简单 控制更精准 t.join();

实现粒度低。 【无法同时多个线程的run()实现】

CycleWait
package thread;

/**
 * @Author bennyrhys
 * @Date 2020-03-27 20:49
 */
public class CycleWait implements Runnable{

    private String value;

    @Override
    public void run() {
        try {
            Thread.sleep(3000);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        value = "we have data now";
    }


    public static void main(String[] args) throws InterruptedException {
        CycleWait cw = new CycleWait();
        Thread t = new Thread(cw);
        t.start();

//        // 主线程等待法
//        while (cw.value == null) {
//            Thread.sleep(100);
//        }

        // join法阻塞当前线程执行后执行 we have data now
        t.join();

        // 未加等待法 null, 加了等待法 we have data now
        System.out.println(cw.value);

    }
}

通过Callable接口实现:通过FutureTask Or 线程池获取

线程池实现提交多个Callable的类,去让线程池并发的处理结果。 统一对Callable的类进行统一的管理

MyCallable
package thread;

import java.util.concurrent.Callable;

/**
 * @Author bennyrhys
 * @Date 2020-03-27 21:26
 */
public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        String value = "test";
        System.out.println("Ready to work");
        Thread.sleep(5000);
        System.out.println("task done");
        return value;
    }
}
MyCallableMain-FutrueTask接收
package thread;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
FutrueTask接收
 * @Author bennyrhys
 * @Date 2020-03-27 21:34
 */
public class MyCallableMain {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<String> task = new FutureTask<>(new MyCallable());
        new Thread(task).start();
        if (!task.isDone()) {
            System.out.println("task has not finished, please wait");
        }
        System.out.println("task return" + task.get());
    }
}

task has not finished, please wait Ready to work(五秒后) task done task returntest

ThreadPoolDemo-线程池接收
package thread;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * 线程池接收
 * @Author bennyrhys
 * @Date 2020-03-27 21:56
 */
public class ThreadPoolDemo {
    public static void main(String[] args) {
        // 创建线程池
        ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
        Future<String> future = newCachedThreadPool.submit(new MyCallable());

        if (!future.isDone()) {
            System.out.println("task has not finished, please wait!");
        }

        try {
            System.out.println(future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            // 关闭线程池
            newCachedThreadPool.shutdown();
        }
    }
}

task has not finished, please wait! Ready to work task done test

源码理解

接收的FutrueTask->Runnable FutrueTask实现的方法

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

线程池

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

线程的状态

官方说法及源码

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

六个状态

新建:未start() 运行:调用了start(),Ready获得cpu的使用时间后->Running 无限期等待:需要被显示的唤醒,nodef 结束:线程一旦终止不能复生。终止的再调start()会抛异常

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

Sleep和Wait的区别

差别

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

源码

wait()唤醒阻塞, 即使不传参,调用的也是带参数的,无限期等待

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

代码-通过等待时间唤醒wait()

package thread;

/**
 * @Author bennyrhys
 * @Date 2020-03-28 16:05
 * 先锁定的状态
 * Thread A is waiting to get lock
 * Thread A get lock
 * Thread B is waiting to get lock
 * Thread A do wait method
 * Thread B get lock
 * Thread B is sleeping 10ms
 * Thread B is done
 * Thread A is done
 *
 * 翻转情况-a不释放锁,一直到执行完毕
 * Thread A is waiting to get lock
 * Thread A get lock
 * Thread B is waiting to get lock
 * Thread A do wait method
 * Thread A is done
 * Thread B get lock
 * Thread B is sleeping 10ms
 * Thread B is done
 */

public class WaitSleepDemo {
    public static void main(String[] args) {
        // wait()必须由Object创建
        final Object lock = new Object();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Thread A is waiting to get lock");
                synchronized (lock) {
                    try {
                        System.out.println("Thread A get lock");
                        Thread.sleep(20);
                        System.out.println("Thread A do wait method");
                        Thread.sleep(1000);
//                        lock.wait(1000);
                        System.out.println("Thread A is done");
                    }catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        // 强制上方线程先执行
        try {
            Thread.sleep(10);
        }catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Thread B is waiting to get lock");
                synchronized (lock) {
                    try {
                        System.out.println("Thread B get lock");
                        System.out.println("Thread B is sleeping 10ms");
                        lock.wait(10);
//                        Thread.sleep(10);
                        System.out.println("Thread B is done");
                    }catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

    }
}

代码-通过notify和notifyAll唤醒wait()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
package thread;

/**
 * @Author bennyrhys
 * @Date 2020-03-28 16:05
 * 先锁定的状态
 * Thread A is waiting to get lock
 * Thread A get lock
 * Thread B is waiting to get lock
 * Thread A do wait method
 * Thread B get lock
 * Thread B is sleeping 10ms
 * Thread B is done
 * Thread A is done
 *
 * 翻转情况-a不释放锁,一直到执行完毕
 * Thread A is waiting to get lock
 * Thread A get lock
 * Thread B is waiting to get lock
 * Thread A do wait method
 * Thread A is done
 * Thread B get lock
 * Thread B is sleeping 10ms
 * Thread B is done
 */

public class WaitSleepDemo {
    public static void main(String[] args) {
        // wait()必须由Object创建
        final Object lock = new Object();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Thread A is waiting to get lock");
                synchronized (lock) {
                    try {
                        System.out.println("Thread A get lock");
                        Thread.sleep(20);
                        System.out.println("Thread A do wait method");
//                        Thread.sleep(1000);
                        lock.wait(); // 进入无限的等待当中

                        System.out.println("Thread A is done");
                    }catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        // 强制上方线程先执行
        try {
            Thread.sleep(10);
        }catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Thread B is waiting to get lock");
                synchronized (lock) {
                    try {
                        System.out.println("Thread B get lock");
                        System.out.println("Thread B is sleeping 10ms");
//                        lock.wait(10);
                        Thread.sleep(10);
                        System.out.println("Thread B is done");
                        lock.notifyAll(); // 用其他线程 唤醒沉睡的线程
                    }catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

    }
}

notify和notifyall的区别

概念-等待池-锁池

多线程抢占锁,如果某对象没有竞争到锁,只会留在锁池中,不会在等待池中

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

区别

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

代码-区分唤醒一个,全部唤醒【对锁造成的影响】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
import java.util.logging.Level;
import java.util.logging.Logger;

public class NotificationDemo {
    private volatile boolean go = false;

    public static void main(String args[]) throws InterruptedException {
        final NotificationDemo test = new NotificationDemo();

        Runnable waitTask = new Runnable(){

            @Override
            public void run(){
                try {
                    test.shouldGo();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " finished Execution");
            }
        };

        Runnable notifyTask = new Runnable(){

            @Override
            public void run(){
                test.go();
                System.out.println(Thread.currentThread().getName() + " finished Execution");
            }
        };

        Thread t1 = new Thread(waitTask, "WT1"); //will wait
        Thread t2 = new Thread(waitTask, "WT2"); //will wait
        Thread t3 = new Thread(waitTask, "WT3"); //will wait
        Thread t4 = new Thread(notifyTask,"NT1"); //will notify

        //starting all waiting thread
        t1.start();
        t2.start();
        t3.start();

        //pause to ensure all waiting thread started successfully
        Thread.sleep(200);

        //starting notifying thread
        t4.start();

    }
    /*
     * wait and notify can only be called from synchronized method or bock
     */
    private synchronized void shouldGo() throws InterruptedException {
        while(go != true){
            System.out.println(Thread.currentThread()
                    + " is going to wait on this object");
            wait(); //release lock and reacquires on wakeup
            System.out.println(Thread.currentThread() + " is woken up");
        }
        go = false; //resetting condition
    }

    /*
     * both shouldGo() and go() are locked on current object referenced by "this" keyword
     */
    private synchronized void go() {
        while (go == false){
            System.out.println(Thread.currentThread()
                    + " is going to notify all or one thread waiting on this object");

            go = true; //making condition true for waiting thread
            //notify(); // only one out of three waiting thread WT1, WT2,WT3 will woke up
            notifyAll(); // all waiting thread  WT1, WT2,WT3 will woke up
        }

    }
}

yield函数

概念

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

代码-体会暗示,随机

public class YieldDemo {
    public static void main(String[] args) {
        Runnable yieldTask = new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 10; i++) {
                    System.out.println(Thread.currentThread().getName() + i);
                    if (i == 5) {
                        Thread.yield();
                    }
                }
            }
        };
        Thread t1 = new Thread(yieldTask, "A");
        Thread t2 = new Thread(yieldTask, "B");
        t1.start();
        t2.start();
    }
}

到5切换线程,接受暗示

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

到5不切换线程,忽略暗示

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

代码-yield对锁的影响-不会放弃当前锁

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

如何中断线程

废弃

stop()一个线程,调用另一个线程停止。 这种不妥,未知另一个状态,导致线程无法清理完成释,放锁,数据异常。

interrupt() 暗示通知线程该中断

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

代码-对Interrupt的验证

public class InterruptDemo {
    public static void main(String[] args) throws InterruptedException {
        Runnable interruptTask = new Runnable() {
            @Override
            public void run() {
                int i = 0;
                try {
                    //在正常运行任务时,经常检查本线程的中断标志位,如果被设置了中断标志就自行停止线程
                    while (!Thread.currentThread().isInterrupted()) {
                        Thread.sleep(100); // 休眠100ms
                        i++;
                        System.out.println(Thread.currentThread().getName() + " (" + Thread.currentThread().getState() + ") loop " + i);
                    }
                } catch (InterruptedException e) {
                    //在调用阻塞方法时正确处理InterruptedException异常。(例如,catch异常后就结束线程。)
                    System.out.println(Thread.currentThread().getName() + " (" + Thread.currentThread().getState() + ") catch InterruptedException.");
                }
            }
        };
        Thread t1 = new Thread(interruptTask, "t1");
        System.out.println(t1.getName() +" ("+t1.getState()+") is new.");

        t1.start();                      // 启动“线程t1”
        System.out.println(t1.getName() +" ("+t1.getState()+") is started.");

        // 主线程休眠300ms,然后主线程给t1发“中断”指令。
        Thread.sleep(300);
        t1.interrupt();
        System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");

        // 主线程休眠300ms,然后查看t1的状态。
        Thread.sleep(300);
        System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
    }
}
在这里插入图片描述
在这里插入图片描述

前述方法及线程状态总结

在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-03-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 线程和进程的区别
    • JDK选择长期版本
      • 线程和进程的区别
        • 基础
        • 由来
        • 区别
        • 关系
        • 代码查看主线程
    • Thread中的start方法和run方法的区别
      • 效果图
        • 代码
          • 分析源码
            • 没有可比性run和star
            • Thread和Runnable是什么关系
              • 本质
                • 源码
                  • 代码演示
                    • 普通Thread.start()线程-效果图
                    • MyThread
                    • 通过Thread类启动Runnable多线程-效果图
                    • MyRunnalbe
                    • MyRunnableMain
                • 如何实现处理线程的返回值
                  • 如何给run()方法传参
                    • 实现的方式主要有三种
                      • 主线程等待法
                      • Thread类join()方法阻塞当前线程,等待当前子线程执行完毕
                      • 通过Callable接口实现:通过FutureTask Or 线程池获取
                  • 线程的状态
                    • 官方说法及源码
                      • 六个状态
                      • Sleep和Wait的区别
                        • 差别
                          • 源码
                        • 代码-通过等待时间唤醒wait()
                          • 代码-通过notify和notifyAll唤醒wait()
                          • notify和notifyall的区别
                            • 概念-等待池-锁池
                              • 区别
                                • 代码-区分唤醒一个,全部唤醒【对锁造成的影响】
                                • yield函数
                                  • 概念
                                    • 代码-体会暗示,随机
                                      • 代码-yield对锁的影响-不会放弃当前锁
                                      • 如何中断线程
                                        • 废弃
                                          • interrupt() 暗示通知线程该中断
                                            • 代码-对Interrupt的验证
                                            • 前述方法及线程状态总结
                                            领券
                                            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档