线程池的核心操作:
1.execute:把一个任务加入到线程池中
2.shutdown:销毁线程池中的所有线程
线程池组成部分:
1.现有一个类,表示工作线程
2.还得有一个类,来描述具体线程要做的工作是啥
3.需要有一个数据结构来组织若干任务
4.还需要一个数据结构来组织若干线程
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
class MyThreadPool {
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
List<Worker> workers = new ArrayList<>();
final int maxWorkerCount = 10;
public void execute(Runnable command) throws InterruptedException {
if (workers.size()<maxWorkerCount) {
Worker worker = new Worker(queue);
worker.start();
workers.add(worker);
}
queue.put(command);
}
public void shutdown() throws InterruptedException {
for (Worker worker:workers) {
worker.interrupt();
}
for (Worker worker:workers) {
worker.join();
}
}
}
class Worker extends Thread{
BlockingQueue<Runnable> queue = null;
public Worker(BlockingQueue<Runnable> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
Runnable command = queue.take();
command.run();
}
} catch (InterruptedException e) {
System.out.println("线程被终止");
}
}
}
public class ThreadDemo {
public static void main(String[] args) throws InterruptedException {
MyThreadPool pool = new MyThreadPool();
for(int i = 0;i<1000;i++) {
pool.execute(new Runnable() {
@Override
public void run() {
System.out.println("我在执行任务:");
}
});
}
Thread.sleep(2000);
pool.shutdown();
System.out.println("线程已经被销毁");
}
}
事务并发执行时的问题
1.脏读
如果一个事物A正在修改数据但还没提交,另一个事务B读取了这里的修改内容,此时事务B的读操作就是脏读。
解决办法:给写操作进行加锁。
2.不可重复读
一个事物A执行过程中,两次读取到的数据不相同,就叫不可重复读。
解决方案:读也加锁,在读的时候不能修改
3.幻读
一次事务执行过程中,多次读取到的结果集不一样(具体的结果数据是一致的)
解决方案:让读和写彻底串行化
MySQL的隔离级别
1.read uncommitted:允许读取未提交的数据
2.read committed:只允许读取已经提交的数据
3.repeatable read:给读也加锁,解决了不可重复读,但还有幻读问题。
4.serializable:严格串行执行