并发编程学前准备
cpu是如何执行程序的
存储层次
缓存一致性问题
解决方法:
(硬件层次)
在java中只需要加volatile关键字即可
利用空间局部性
缓存一次读64字节,每次读数据会把相邻的数据读进来
问题:
核心1改了A的数据会导致核心2的数据全部失效,核心2只能重新再读一遍AB
解决方法:
使用缓存行填充:
添加无用的多余数据填充数据至64字节,使一个数据占一个缓存行(dispute)
三种方式创建线程
//1 定义类并集成Thread类
//2 重写run方法
public class MyThread extends Thread{
//run()实际启动线程后执行的方法
@Override
public void run() {
System.out.println("MyThread 线程启动了 ,线程的名字:"+this.getName());
}
}
//测试
public class TestMyThread {
public static void main(String[] args) {
//3 创建子类对象
MyThread myThread = new MyThread();
myThread.setName("myThread");
//4 调用start()启动线程
myThread.start();
// myThread.run();
System.out.println(Thread.currentThread().getName());
}
}
//1 定义一个类实现Runnable接口
//2 重写run方法
public class MyRunnable implements Runnable{
//线程具体做对的事情
@Override
public void run() {
System.out.println("MyRunnable 线程启动了 线程的名字"+ Thread.currentThread().getName());
}
}
//测试
public class TestMyRunnable {
public static void main(String[] args) {
//3 实现这个类
MyRunnable myRunnable = new MyRunnable(); //任务
Thread thread1 = new Thread(myRunnable);
Thread thread2 = new Thread(myRunnable);
Thread thread3 = new Thread(myRunnable);
//4 使用MyRunnable的对象构造Thread
Thread thread = new Thread(myRunnable);
thread.setName("myRunnable");
//5启动线程
thread.start();
}
}
//1 定义一个类实现Callable接口
//2 重写Callable接口中的call()方法
public class MyCallable implements Callable {
//线程具体做的事情,并返回一个随机的(0-5)int值
@Override
public Integer call() throws Exception {
return new Random().nextInt(5);
}
}
public class TestCallable {
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
//3 创建Mycallable类的对象
MyCallable myCallable = new MyCallable();
//4 把第三步的对象作为构造方法的参数创建FutureTask类的对象
FutureTask<Integer> futureTask = new FutureTask(myCallable);
//5 把第四步创建的FutureTask类的对象作为构造方法的参数创建Thread类的对象
Thread thread = new Thread(futureTask);
thread.start();
Thread.sleep(2000);
Integer integer = futureTask.get(3, TimeUnit.SECONDS);
System.out.println(integer);
}
}
join方法
其他线程执行完后,当前线程再执行(先预热,主线程才能烤面包)
public class TestJoin {
public static void main(String[] args) throws InterruptedException {
long startTime = System.currentTimeMillis();
//1 创建一个线程去烤箱预热
Thread preHeatThread = new Thread(()->{
System.out.println("烤箱预热开始");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("烤箱预热结束");
});
preHeatThread.start();
//2 主线程切面包
System.out.println("主线程开始切面包");
Thread.sleep(2000);
//3 主线程等待烤箱预热结束
preHeatThread.join();
System.out.println("预热结束"+ (System.currentTimeMillis()-startTime));
//4 烤面包
System.out.println("开始烤面包");
}
}
线程中断
场景:
方法1:使用Interrupt(),当一个线程的 interrupt 属性被设置为true后,这次线程执行完后就会停止执行,sleep方法会在抛出异常的同时把线程的Interrupt属性设置为false。
public class TestInterrupt {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(()->{
while (!Thread.currentThread().isInterrupted()){
//do work
System.out.println("第一个动作:付款");
System.out.println("第二个动作:生成订单");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("休眠被中断");
Thread.currentThread().interrupt();
}
}
});
thread.start();
Thread.sleep(100);
thread.interrupt();
}
}