彻底搞懂Java多线程(一)

目录
  • Java多线程
    • 线程的创建
    • 线程常用方法
    • 线程的终止
      • 1.自定义实现线程的终止
      • 2.使用Thread的interrupted来中断
      • 3.Thraed.interrupted()方法和Threaed.currentThread().interrupt()的区别
      • 线程的状态
      • 线程的优先级
      • 守护线程
      • 线程组
      • 线程安全问题
    • volatile关键字
  • 总结

Java多线程

线程的创建

1.继承Thread

2.实现Runnable

3.实现Callable

使用继承Thread类来开发多线程的应用程序在设计上是有局限性的,因为Java是单继承。

继承Thread类

public class ThreadDemo1 {
    // 继承Thread类 写法1
    static class MyThread extends Thread{
        @Override
        public void run() {
            //要实现的业务代码
        }
    }
    // 写法2
    Thread thread = new Thread(){
        @Override
        public void run() {
            //要实现的业务代码
        }
    };
}

实现Runnable接口

//实现Runnable接口 写法1
class MyRunnable implements Runnable{
    @Override
    public void run() {
        //要实现的业务代码
    }
}
//实现Runnable接口 写法2 匿名内部类
class MyRunnable2 {
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                //要实现的业务代码
            }
        });
    }
}

实现Callable接口(Callable + FutureTask 创建带有返回值的线程)

package ThreadDeom;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
 * user:ypc;
 * date:2021-06-11;
 * time: 17:34;
 */
//创建有返回值的线程 Callable + Future
public class ThreadDemo2 {
    static class MyCallable implements Callable<Integer>{
        @Override
        public Integer call() throws Exception {
            return 0;
        }
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建Callable子对象
        MyCallable myCallable = new MyCallable();
        //使用FutureTask 接受 Callable
        FutureTask<Integer> futureTask = new FutureTask<>(myCallable);
        //创建线程并设置任务
        Thread thread = new Thread(futureTask);
        //启动线程
        thread.start();
        //得到线程的执行结果
        int num = futureTask.get();
    }
}

也可以使用lambda表达式

class ThreadDemo21{
    //lambda表达式
    Thread thread = new Thread(()-> {
        //要实现的业务代码
    });
}

Thread的构造方法

线程常用方法

获取当前线程的引用、线程的休眠

class Main{
    public static void main(String[] args) throws InterruptedException {
        Thread.sleep(1000);
        //休眠1000毫秒之后打印
        System.out.println(Thread.currentThread());
        System.out.println(Thread.currentThread().getName());
    }
}

package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-11;
 * time: 18:38;
 */
public class ThreadDemo6 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("线程的ID:" + Thread.currentThread().getId());
                System.out.println("线程的名称:" + Thread.currentThread().getName());
                System.out.println("线程的状态:" + Thread.currentThread().getState());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"线程一");
        thread.start();
        Thread.sleep(100);
        //打印线程的状态
        System.out.println("线程的状态:"+thread.getState());
        System.out.println("线程的优先级:"+thread.getPriority());
        System.out.println("线程是否存活:"+thread.isAlive());
        System.out.println("线程是否是守护线程:"+thread.isDaemon());
        System.out.println("线程是否被打断:"+thread.isInterrupted());
    }
}

线程的等待

假设有一个坑位,thread1 和 thread2 都要上厕所。一次只能一个人上,thread2只能等待thread1使用完才能使用厕所。就可以使用join()方法,等待线程1执行完,thread2在去执行。👇

package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-12;
 * time: 10:48;
 */
public class ThreadDemo13 {
    public static void main(String[] args) throws InterruptedException {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"🚾");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"出来了");
            }
        };
        Thread t1 = new Thread(runnable,"thread1");
        t1.start();
        //t1.join();
        Thread t2 = new Thread(runnable,"thread2");
        t2.start();
    }
}

没有join()显然是不行的。加上join()之后:

线程的终止

1.自定义实现线程的终止

package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-12;
 * time: 9:59;
 */
public class ThreadDemo11 {
    private static boolean flag = false;
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!flag){
                    System.out.println("我是 : " + Thread.currentThread().getName() + ",我还没有被interrupted呢");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("我是 "+Thread.currentThread().getName()+",我被interrupted了");
            }
        },"thread");
        thread.start();
        Thread.sleep(300);
        flag = true;
    }
}

2.使用Thread的interrupted来中断

package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-12;
 * time: 9:59;
 */
public class ThreadDemo11 {
//    private static boolean flag = false;
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!Thread.interrupted()){
                    System.out.println("我是 : " + Thread.currentThread().getName() + ",我还没有被interrupted呢");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
//                        e.printStackTrace();
                        break;
                    }
                }
                System.out.println("我是 "+Thread.currentThread().getName()+",我被interrupted了");
            }
        },"thread");
        thread.start();
        Thread.sleep(300);
        thread.interrupt();
//        flag = true;
    }
}

3.Thraed.interrupted()方法和Threaed.currentThread().interrupt()的区别

Thread.interrupted()方法第一次接收到终止的状态后,之后会将状态复位,Thread.interrupted()是静态的,是全局的。

Threaed.currentThread().interrupt()只是普通的方法。

Thraed.interrupted()方法

package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-12;
 * time: 10:32;
 */
public class ThreadDemo12 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() ->{
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.interrupted());
            }
        });
        thread.start();
        thread.interrupt();
    }
}

Threaed.currentThread().interrupt()

package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-12;
 * time: 10:32;
 */
public class ThreadDemo12 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() ->{
            for (int i = 0; i < 10; i++) {
//                System.out.println(Thread.interrupted());
                System.out.println(Thread.currentThread().isInterrupted());
            }
        });
        thread.start();
        thread.interrupt();
    }
}

yield()方法

让出CPU的执行权

package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-12;
 * time: 11:47;
 */
public class ThreadDemo15 {
    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                Thread.yield();
                System.out.println("thread1");
            }
        });
        thread1.start();
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                System.out.println("thread2");
            }
        });
        thread2.start();
    }
}

线程的状态

打印出线程的所有的状态,所有的线程的状态都在枚举中。👇

package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-12;
 * time: 11:06;
 */
public class ThreadDemo14 {
    public static void main(String[] args) {
        for (Thread.State state: Thread.State.values()) {
            System.out.println(state);
        }
    }
}

  • NEW 创建了线程但是还没有开始工作
  • RUNNABLE 正在Java虚拟机中执行的线程
  • BLOCKED 受到阻塞并且正在等待某个监视器的锁的时候所处的状态
  • WAITTING 无限期的等待另一个线程执行某个特定操作的线程处于这个状态
  • TIME_WAITTING 有具体等待时间的等待
  • TERMINATED 已经退出的线程处于这种状态
package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-12;
 * time: 11:06;
 */
class TestThreadDemo{
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        System.out.println(thread.getState());
        thread.start();
        System.out.println(thread.getState());
        Thread.sleep(100);
        System.out.println(thread.getState());
        thread.join();
        System.out.println(thread.getState());
    }
}

线程的优先级

在Java中线程 的优先级分为1 ~ 10 一共十个等级

package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-11;
 * time: 21:22;
 */
public class ThreadDemo9 {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("t1");
                }
            });
            //最大优先级
            t1.setPriority(10);
            t1.start();
            Thread t2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("t2");
                }
            });
            //最小优先级
            t2.setPriority(1);
            t2.start();
            Thread t3 = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("t3");
                }
            });
            t3.setPriority(1);
            t3.start();
        }
    }
}

线程的优先级不是绝对的,只是给程序的建议。

线程之间的优先级具有继承的特性,如果A线程启动了B线程,那么B的线程的优先级与A是一样的。👇

package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-11;
 * time: 20:46;
 */
class ThreadA extends Thread{
    @Override
    public void run() {
        System.out.println("ThreadA优先级是:" + this.getPriority());
        ThreadB threadB = new ThreadB();
        threadB.start();
    }
}
class ThreadB extends ThreadA{
    @Override
    public void run() {
        System.out.println("ThreadB的优先级是:" + this.getPriority());
    }
}
public class ThreadDemo7 {
    public static void main(String[] args) {
        System.out.println("main线程开始的优先级是:" + Thread.currentThread().getPriority());
        System.out.println("main线程结束的优先级是:" + Thread.currentThread().getPriority());
        ThreadA threadA = new ThreadA();
        threadA.start();
    }
}

再看👇

package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-11;
 * time: 20:46;
 */
class ThreadA extends Thread{
    @Override
    public void run() {
        System.out.println("ThreadA优先级是:" + this.getPriority());
        ThreadB threadB = new ThreadB();
        threadB.start();
    }
}
class ThreadB extends ThreadA{
    @Override
    public void run() {
        System.out.println("ThreadB的优先级是:" + this.getPriority());
    }
}
public class ThreadDemo7 {
    public static void main(String[] args) {
        System.out.println("main线程开始的优先级是:" + Thread.currentThread().getPriority());
        Thread.currentThread().setPriority(9);
        System.out.println("main线程结束的优先级是:" + Thread.currentThread().getPriority());
        ThreadA threadA = new ThreadA();
        threadA.start();
    }
}

结果为👇

守护线程

Java中有两种线程:一种是用户线程,一种就是守护线程。

什么是守护线程?守护线程是一种特殊的线程,当进程中不存在用户线程的时候,守护线程就会自动销毁。典型的守护线程就是垃圾回收线程,当进程中没有了非守护线程,则垃圾回收线程也就没有存在的必要了。

Daemon线程的作用就是为其他线程的运行提供便利的。👇

package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-11;
 * time: 21:06;
 */
public class ThreadDemo8 {
    static private int i = 0;
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    i++;
                    System.out.println(i);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        //设置守护线程
        thread.setDaemon(true);
        thread.start();
        Thread.sleep(5000);
        System.out.println("我是守护线程thread 当用户线程执行完成后 我也就销毁了😭哭了");
    }
}

注意:守护线程的设置必须放在start()之前,否则就会报错。

在守护线程中创建的线程默认也是守护线程。

package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-12;
 * time: 9:35;
 */
public class ThreadDemo10 {
    public static void main(String[] args) {
        Thread thread1 = new Thread(()->{
            Thread thread2 = new Thread(() -> {
            },"thread2");
            System.out.println("thread2是守护线程吗?:" + thread2.isDaemon());
        },"thread1");
        System.out.println("thread1是守护线程吗?:" + thread1.isDaemon());
        //thread1.setDaemon(true);
        thread1.start();
       // System.out.println("thread1是守护线程吗?:" + thread1.isDaemon());
    }
}

再看👇

package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-12;
 * time: 9:35;
 */
public class ThreadDemo10 {
    public static void main(String[] args) {
        Thread thread1 = new Thread(()->{
            Thread thread2 = new Thread(() -> {
            },"thread2");
            System.out.println("thread2是守护线程吗?:" + thread2.isDaemon());
        },"thread1");
        System.out.println("thread1是守护线程吗?:" + thread1.isDaemon());
        thread1.setDaemon(true);
        thread1.start();
        System.out.println("thread1是守护线程吗?:" + thread1.isDaemon());
    }
}

线程组

为了便于对某些具有相同功能的线程进行管理,可以把这些线程归属到同一个线程组中,线程组中既可以有线程对象,也可以有线程组,组中也可以有线程。使用线程模拟赛跑

public class ThreadDemo5 {
    //线程模拟赛跑(未使用线程分组)
    public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "到达了终点");
            }
        }, "选手一");
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "到达了终点");
            }
        }, "选手二");
        t1.start();
        t2.start();
        System.out.println("所有选手到达了终点");
    }
}

运行结果:

不符合预期效果,就可以使用线程组来实现

package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-11;
 * time: 18:24;
 */
class ThreadGroup1 {
    //线程分组模拟赛跑
    public static void main(String[] args) {
        ThreadGroup threadGroup = new ThreadGroup("Group");
        Thread t1 = new Thread(threadGroup, new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("选手一到达了终点");
            }
        });
        Thread t2 = new Thread(threadGroup, new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("选手二到达了终点");
            }
        });
        t2.start();
        t1.start();
        while (threadGroup.activeCount() != 0) {
        }
        System.out.println("所有选手到达了终点");
    }
}

线程组常用的方法

线程安全问题

来看单线程情况下让count分别自增和自减10000次

package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-12;
 * time: 12:03;
 */
class Counter {
    private static int count = 0;
    public void increase(){
        for (int i = 0; i < 10000; i++) {
            count++;
        }
    }
    public void decrease(){
        for (int i = 0; i < 10000; i++) {
            count--;
        }
    }
    public int getCount(){
        return count;
    }
}
public class ThreadDemo16 {
    public static void main(String[] args) {
        //单线程
        Counter counter = new Counter();
        counter.increase();
        counter.decrease();
        System.out.println(counter.getCount());
    }
}

结果符合预期

如果想使程序的执行速度快,就可以使用多线程的方式来执行。在来看多线程情况下的问题

public class ThreadDemo16 {
    public static void main(String[] args) throws InterruptedException {
        //多线程情况下
        Counter counter = new Counter();
        Thread thread1 = new Thread(()->{
            counter.decrease();
        });
        Thread thread2 = new Thread(()->{
            counter.increase();
        });
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(counter.getCount());
                /*
        //单线程
        Counter counter = new Counter();
        counter.increase();
        counter.decrease();
        System.out.println(counter.getCount());
         */
    }
}

执行结果:

每次的执行结果是不一样的。这就是多线程的不安全问题

预期的结果是0,但结果却不是。线程不安全问题的原因:

  • 1.CPU的抢占式执行
  • 2.多个线程共同操作一个变量
  • 3.内存可见性
  • 4.原子性问题
  • 5.编译器优化(指令重排)

多个线程操作同一个变量

如果多个线程操作的不是一个变量,就不会发生线程的不安全问题,可以将上面的代码修改如下:👇

public class ThreadDemo16 {
    static int res1 = 0;
    static int res2 = 0;
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                res1 = counter.getCount();
            }
        });
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                res2 = counter.getCount();
            }
        });
        System.out.println(res1 + res2);
/*
        //多线程情况下
        Counter counter = new Counter();
        Thread thread1 = new Thread(()->{
            counter.decrease();
        });
        Thread thread2 = new Thread(()->{
            counter.increase();
        });
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(counter.getCount());
        */
                /*
        //单线程
        Counter counter = new Counter();
        counter.increase();
        counter.decrease();
        System.out.println(counter.getCount());
         */
    }
}

这样就可以了:

内存不可见问题:看下面的代码,是不是到thread2执行的时候,就会改变num的值,从而终止了thread1呢?

package ThreadDeom;
import java.util.Scanner;
/**
 * user:ypc;
 * date:2021-06-12;
 * time: 13:03;
 */
public class ThreadDemo17 {
    private static int num = 0;
    public static void main(String[] args) {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (num == 0){}
            }
        });
        thread1.start();
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                Scanner scanner = new Scanner(System.in);
                System.out.println("输入一个数字来终止线程thread1");
                num = scanner.nextInt();
            }
        });
        thread2.start();
    }
}

结果是不能的:

输入一个数字后回车,并没有让thread1的循环结束。这就是内存不可见的问题。

原子性的问题

上面的++和–操作其实是分三步来执行的

假设在第二部的时候,有另外一个线程也来修改值,那么就会出现脏数据的问题了。

所以就会发生线程的不安全问题

编译器优化编译器的优化会打乱原本程序的执行顺序,就有可能导致线程的不安全问题发生。在单线程不会发生线程的不安全问题,在多线程就可能会不安全。

volatile关键字

可以使用volatile关键字,这个关键字可以解决指令重排和内存不可见的问题。

加上volatile关键字之后的运行结果

但是volatile关键字不能解决原子性的问题👇:

package ThreadDeom;
/**
 * user:ypc;
 * date:2021-06-12;
 * time: 14:02;
 */
class Counter1 {
    private static volatile int count = 0;
    public void increase() {
        for (int i = 0; i < 10000; i++) {
            count++;
        }
    }
    public void decrease() {
        for (int i = 0; i < 10000; i++) {
            count--;
        }
    }
    public int getCount() {
        return count;
    }
}
public class ThreadDemo18 {
    public static void main(String[] args) throws InterruptedException {
        Counter1 counter1 = new Counter1();
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                counter1.decrease();
            }
        });
        Thread thread2 = new Thread(() -> {
            counter1.increase();
        });
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(counter1.getCount());
    }
}

总结

本篇文章就到这里,希望可以帮到你,也希望您能够多多关注我们的其他文章!

(0)

相关推荐

  • 彻底搞懂Java多线程(一)

    目录 Java多线程 线程的创建 线程常用方法 线程的终止 1.自定义实现线程的终止 2.使用Thread的interrupted来中断 3.Thraed.interrupted()方法和Threaed.currentThread().interrupt()的区别 线程的状态 线程的优先级 守护线程 线程组 线程安全问题 volatile关键字 总结 Java多线程 线程的创建 1.继承Thread 2.实现Runnable 3.实现Callable 使用继承Thread类来开发多线程的应用程序

  • 彻底搞懂Java多线程(五)

    目录 单例模式与多线程 立即加载/饿汉模式 延时加载/懒汉模式 饿汉/懒汉对比 阻塞队列的实现 常见的锁策略 乐观锁 CAS CAS在java中的应用 CAS 的ABA问题 ABA 问题的解决 悲观锁 独占锁.共享锁.自旋锁.可重入锁 详解synchronized锁的优化问题 Semaphore Semaphore的作用: Semaphore实现原理: Semaphore的使用: CountDownLatch\CyclicBarrier CountDownLatch CountDownLatch

  • 彻底搞懂Java多线程(四)

    目录 SimpleDateFormat非线程安全问题 ThreadLocal ThreadLocal的原理 ThreadLocal常用方法 ThreadLocal的初始化 InheritableThreadLocal的使用 总结 SimpleDateFormat非线程安全问题 实现1000个线程的时间格式化 package SimpleDateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java

  • 彻底搞懂Java多线程(三)

    目录 Java线程池 线程池的优点 线程池的6种创建方式 创建单个线程池的作用是什么? 线程池的第七种创建方式 ThreadPoolExecutor的执行方式 ThreadPoolExecutor的执行流程 线程池的终止 线程池的状态 异步.同步 1.Java 线程 同步与异步 线程工厂 总结 Java线程池 线程的缺点: 1.线程的创建它会开辟本地方法栈.JVM栈.程序计数器私有的内存,同时消耗的时候需要销毁以上三个区域,因此频繁的创建和销毁线程比较消耗系统的资源. 2.在任务量远远大于线程可

  • 彻底搞懂Java多线程(二)

    目录 Java中的锁 1.synchronized锁(jvm层的解决方案,也叫监视器锁) 2.手动锁Lock synchronized锁 synchronized使用场景 1.使用synchronized来修饰代码块(可以给任意的对象进行加锁操作) 2.使用synchronized来修饰静态方法(对当前的类进行加锁的操作) 3.使用synchronized来修饰普通的方法(对当前类的实例来进行加锁) synchronized注意事项 1.加锁的时候一定要使用同一把锁对象 Lock锁使用的注意事项

  • 一文彻底搞懂java多线程和线程池

    目录 什么是线程 一. Java实现线程的三种方式 1.1.继承Thread类 1.2.实现Runnable接口,并覆写run方法 二. Callable接口 2.1 Callable接口 2.2 Future接口 2.3 Future实现类是FutureTask. 三. Java线程池 3.1.背景 3.2.作用 3.3.应用范围 四. Java 线程池框架Executor 4.1.类图: 4.2 核心类ThreadPoolExecutor: 4.3 ThreadPoolExecutor逻辑结

  • Java基础:彻底搞懂java多线程

    目录 进程与线程 使用多线程的优势 线程的状态 创建线程 线程中断 总结 进程与线程 进程 进程是操作系统结构的基础,是程序在一个数据集合上运行的过程,是系统进行资源分配和调度的基本单位.进程可以被看作程序的实体,同样,它也是程序的容器. 线程 线程是操作系统调度的最小单元,也叫作轻量级进程.在一个进程中可以创建多个线程,这些线程都拥有各自的计数器.堆栈和局部变量等属性. 使用多线程的优势 使用多线程可以减少程序的响应时间 如果某个操作很耗时,或者陷入长时间的等待,此时程序将不会响应鼠标和键盘等

  • 一文搞懂Java创建线程的五种方法

    目录 题目描述 解题思路 代码详解 第一种 继承Thread类创建线程 第二种:实现Runnable接口创建线程 第三种:实现Callable接口,通过FutureTask包装器来创建Thread线程 第四种:使用ExecutorService.Callable(或者Runnable).Future实现返回结果的线程 第五种:使用ComletetableFuture类创建异步线程,且是据有返回结果的线程 题目描述 Java创建线程的几种方式 Java使用Thread类代表线程,所有线程对象都必须

  • 一文搞懂Java并发AQS的共享锁模式

    目录 概述 自定义共享锁例子 核心原理机制 源码解析 成员变量 共享锁获取acquireShared(int) 共享释放releaseShared(int) 概述 这篇文章深入浅出理解Java并发AQS的独占锁模式讲解了AQS的独占锁实现原理,那么本篇文章在阐述AQS另外一个重要模式,共享锁模式,那什么是共享锁呢? 共享锁可以由多个线程同时获取, 比较典型的就是读锁,读操作并不会产生副作用,所以可以允许多个线程同时对数据进行读操作而不会有线程安全问题,jdk中的很多并发工具比如ReadWrite

  • 一篇文章带你搞懂Java线程池实现原理

    目录 1. 为什么要使用线程池 2. 线程池的使用 3. 线程池核心参数 4. 线程池工作原理 5. 线程池源码剖析 5.1 线程池的属性 5.2 线程池状态 5.3 execute源码 5.4 worker源码 5.5 runWorker源码 1. 为什么要使用线程池 使用线程池通常由以下两个原因: 频繁创建销毁线程需要消耗系统资源,使用线程池可以复用线程. 使用线程池可以更容易管理线程,线程池可以动态管理线程个数.具有阻塞队列.定时周期执行任务.环境隔离等. 2. 线程池的使用 /** *

随机推荐