声明:我是使用了黑马的资源,因为我感觉黑马基础这里讲的通俗易懂些,且对于画图还是满擅长,便于小白理解。
这里再说下线程的转换状态
线程池出现就是为了解决线程的弊端
代码如下,在两个线程之间插入sleep会只有一条线程是因为第一个线程执行完毕后把线程归还给池子,那么此时线程池就有一条空闲的线程,第二个线程看池子的时候会看有没有空闲的线程,如果有就把第一个线程复用。这里没有sleep会有两条线程是因为第一条线程还来不及归还给池子第二个任务就提交过来了,所以线程池只能自己创建个新的线程
创建线程池的第一种方法
//static ExecutorService newCachedThreadPool() 创建一个默认的线程池
//static newFixedThreadPool(int nThreads) 创建一个指定最多线程数量的线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MyThreadPoolDemo {
public static void main(String[] args) throws InterruptedException {
//1,创建一个默认的线程池对象.池子中默认是空的.默认最多可以容纳int类型的最大值.
ExecutorService executorService = Executors.newCachedThreadPool();
//Executors --- 可以帮助我们创建线程池对象
//ExecutorService --- 可以帮助我们控制线程池
executorService.submit(()->{
System.out.println(Thread.currentThread().getName() + "在执行了");
});
//Thread.sleep(2000);
executorService.submit(()->{
System.out.println(Thread.currentThread().getName() + "在执行了");
});
executorService.shutdown();
}
}
创建线程池第二种方法
代码实现,这里论证了参数代表的线程数不是初始值而是最大值
使用断点或者ThreadPoolExecutor强转
//static ExecutorService newFixedThreadPool(int nThreads)
//创建一个指定最多线程数量的线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
public class MyThreadPoolDemo2 {
public static void main(String[] args) {
//参数不是初始值而是最大值
ExecutorService executorService = Executors.newFixedThreadPool(10);
ThreadPoolExecutor pool = (ThreadPoolExecutor) executorService;
System.out.println(pool.getPoolSize());//0
executorService.submit(()->{
System.out.println(Thread.currentThread().getName() + "在执行了");
});
executorService.submit(()->{
System.out.println(Thread.currentThread().getName() + "在执行了");
});
System.out.println(pool.getPoolSize());//2
// executorService.shutdown();
}
}
ThreadPoolExecutor类——自己创建线程池对象的方法
这里面的七个参数比较多,代码实现
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class MyThreadPoolDemo3 {
// 参数一:核心线程数量
// 参数二:最大线程数
// 参数三:空闲线程最大存活时间
// 参数四:时间单位
// 参数五:任务队列
// 参数六:创建线程工厂
// 参数七:任务的拒绝策略
public static void main(String[] args) {
ThreadPoolExecutor pool = new ThreadPoolExecutor(2,5,2,TimeUnit.SECONDS,new ArrayBlockingQueue<>(10), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
pool.submit(new MyRunnable());
pool.submit(new MyRunnable());
pool.shutdown();
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "在执行了");
}
}
创建线程对象参数详解
// 参数一:核心线程数量
// 参数二:最大线程数
// 参数三:空闲线程最大存活时间
// 参数四:时间单位 ---TimeUnit
// 参数五:任务队列 ---让任务在队列中等着,等有线程空闲了,再从这个队列中获取任务并且执行
// 参数六:创建线程工厂 ---按照默认的方式创建线程对象
// 参数七:任务的拒绝策略 ---- 1、什么时候拒绝任务 当提交的任务 > 线程池最大线程数量 + 队列容量
// 2、如何拒绝
volatile关键字——不具备原子性
问题表述
问题代码如下,这里B同学修改了值 但是A同学不知道 始终是在while那里
public class Money {
public static volatile int money = 100000;
}
public class MyThread1 extends Thread {
@Override
public void run() {
while(Money.money == 100000){
}
System.out.println("结婚基金已经不是十万了");
}
}
public class MyThread2 extends Thread {
@Override
public void run() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
Money.money = 90000;
}
}
public class Demo {
public static void main(String[] args) {
MyThread1 t1 = new MyThread1();
t1.setName("小路同学");
t1.start();
MyThread2 t2 = new MyThread2();
t2.setName("小皮同学");
t2.start();
}
}
从JMM角度去理解以上情况
在JMM中堆内存是唯一的,而栈内存是线程独有的,也就是说每个线程都有一个自己的线程栈,这样获取变量值得速度会更快。
解决办法二:使用锁对象的方式:强制线程去看共享数据里的最新值
public class Demo {
public static void main(String[] args) {
MyThread1 t1 = new MyThread1();
t1.setName("小路同学");
t1.start();
MyThread2 t2 = new MyThread2();
t2.setName("小皮同学");
t2.start();
}
}
public class Money {
//定义锁对象
public static Object lock = new Object();
public static volatile int money = 100000;
}
public class MyThread1 extends Thread {
@Override
public void run() {
while(true){
synchronized (Money.lock){
if(Money.money != 100000){
System.out.println("结婚基金已经不是十万了");
break;
}
}
}
}
}
public class MyThread2 extends Thread {
@Override
public void run() {
synchronized (Money.lock) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
Money.money = 90000;
}
}
}