并发和并行
并发: 在同一时刻,多个指令在单一CPU上交替指向
并行:在同一时刻,多个指令在多个CPU上同时执行
2核4线程,4核8线程,8核16线程,16核32线程
基础实现线程的方式
- Thread :继承类 ,无返回
- Runnable :实现接口,无返回
- Callable 核 TaskFurture : 实现接口,有返回
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.setName("自定义线程-1");
MyThread t2 = new MyThread("自定义线程-2");
t1.start();
t2.start();
}
static class MyThread extends Thread{
// int ticket = 100; // 单个线程私有
// static int ticket = 100; // MyThread类启动的多线程共有
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i=1;i<1000;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
public class RunnableMain {
public static void main(String[] args) {
MyRunnable r1 = new MyRunnable();
Thread t1 = new Thread(r1,"自定义线程-1");
Thread t2 = new Thread(t1,"自定义线程-2");
t1.start();
t2.start();
}
static class MyRunnable implements Runnable{
// int ticket = 100; // 线程共享
@Override
public void run() {
for (int i=1;i<1000;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
}
public class CallableMain {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyCallable c1 = new MyCallable();
FutureTask<Integer> f1 = new FutureTask<>(c1);
Thread t1 = new Thread(f1);
t1.start();
System.out.println(f1.get());
}
static class MyCallable implements Callable<Integer>{
@Override
public Integer call() throws Exception {
Integer count = 0;
for (int i=1;i<1000;i++){
count+=i;
}
return count;
}
}
}
常见的成员方法
方法名称 | 说明 |
String getName() | 返回此线程的名称 |
void setName() | 设置线程的名称 |
static Thread currentThread() | 获得当前线程对象 |
static void sleep(long time) | 让当前线程休眠,单位:毫秒 |
setPriority(int newPriority) | 设置线程优先级,1-10,10最大优先级,默认5 |
final int getPriority() | 获取线程的优先级 |
final void setDaemon(boolean on) | 设置为守护线程,其他非守护线程的线程结果,守护线程也将结束 |
public static void yield() | 礼让线程,让线程跑得更均匀 |
public staic void join() | 插入线程,插入得线程跑完再继续执行被插入线程 |
生命周期
同步代码块synchronized (),同步方法,local锁
// lock是接口,用ReentrantLock实现
Lock reentrantLock = new ReentrantLock();
reentrantLock.lock();
reentrantLock.unlock();
注意退出的时候,是否带锁退出,最好放在finally块里
死锁:相互等待
等待/唤醒
锁.wait();
锁.notifyAll(); //唤醒所有
这两个方法必须在同步代码块内部调用
交替执行:
public class MyArrayBlockingQueue {
static Integer count = 10;
static Integer hasFood = 0;
static Object obj = new Object();
public static void main(String[] args) {
Cooker cooker = new Cooker();
Eater eater = new Eater();
Thread t1 = new Thread(cooker);
Thread t2 = new Thread(eater);
t1.start();
t2.start();
}
@Data
static
class Cooker implements Runnable {
private ArrayBlockingQueue abq;
@Override
public void run() {
while (true) {
if (count == 0) {
break;
} else {
synchronized (MyArrayBlockingQueue.obj) {
if (hasFood == 1) {
// 有食物
try {
MyArrayBlockingQueue.obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
hasFood++;
System.out.println("做了一份菜");
MyArrayBlockingQueue.obj.notifyAll();
}
}
}
}
}
}
@Data
static
class Eater implements Runnable {
private ArrayBlockingQueue abq;
@Override
public void run() {
while (true) {
if (count == 0) {
break;
} else {
synchronized (MyArrayBlockingQueue.obj) {
if (hasFood == 0) {
// 没有食物
try {
MyArrayBlockingQueue.obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
hasFood--;
count--;
System.out.println("吃了一份菜,还剩下" + count + "容量的肚子");
MyArrayBlockingQueue.obj.notifyAll();
}
}
}
}
}
}
}
阻塞队列
继承:
Iterable -> Collection -> Queue -> BlockingQueue -> ArrayBlockQueue(数组有界) / LinkedBlockQueue(数组无界)
线程池
// 获取一个单线程的线程池:
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
// 获取FixThread 线程池: 指定活跃线程数量2
ExecutorService executorService = Executors.newFixedThreadPool(2);
// 创建一个可缓存的线程连接池,无限大(完全取决于操作系统最大允许多少)
// 超过60秒自动回收
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
// 1. 获取周期性线程池, 传入核心线程的大小
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
多线程(二) | 彻底搞懂线程池-Executors_executor.submit-CSDN博客