多线程总结

118 阅读1分钟

一、线程安全

什么是线程不安全?

当多线程在访问同一个对象时,会因为其他线程的存在而获得错误结果,则该对象非线程安全。

线程安全的三要素?

有序性(volatile)+可见性(volatile)+原子性(由CAS提供硬件级别的原子操作)

二、线程池是如何实现线程复用?

线程池是对线程和任务的解耦,避免一个thread必须对应一个task的限制。

//一个字段表示两个含义:高3位=runState,低29位=workerCount
final AtomicInteger ctl

BlockingQueue<Runnable> workQueue
HashSet<Worker> workers
volatile ThreadFactory threadFactory;
volatile RejectedExecutionHandler handler;
volatile long keepAliveTime;
volatile int corePoolSize;
volatile int maximumPoolSize;

public void execute(Runnable command) {
    addWorker(command, true);
}

boolean addWorker(Runnable firstTask, boolean core) {
    Worker w = new Worker(firstTask);
    
    Thread t = w.thread;
    
    //启动线程
    t.start(); 
}

class Worker extends AbstractQueuedSynchronizer implements Runnable {
	final Thread thread; //被复用的线程
	Runnable firstTask; //循环获取后被执行的任务

    Worker(Runnable firstTask) {
        setState(-1); // inhibit interrupts until runWorker
        this.firstTask = firstTask;
        this.thread = getThreadFactory().newThread(this);
    }

    public void run() {
        runWorker(this);
    }
}

void runWorker(Worker w) {
	
	//先执行第一个任务
	Runnable task = w.firstTask;
    
    //循环从队列中获取待执行任务
    while (task != null || (task = getTask()) != null) {
        //直接对run方法调用
        task.run();

        //执行结束后销毁,从队列中获取下一个任务
        task = null;
    }
}

//从等待队列中获取任务
Runnable getTask() {
    for (;;) {
        return timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take();
    }
}