新建线程的方法有三种
1、继承Thread类
2、继承runnable接口
3、继承callable
执行线程的方法有两种
1、Thread.start();
2、ExcuteService.excute(new Thread);
线程的五种状态:
1、新建
2、就绪
3、运行
4、阻塞
5、结束
Thread类:
run()和start()要注意一下,run意味着在当前线程执行了实例的某个方法,start意味着开启线程,仅仅是run()的话是没有并行工作的效应的。
yield()暂停线程,不能指定时间,仅仅是可以让同优先级的线程先执行。sleep()线程睡眠可以指定睡眠多少时间,可以让其他线程获得执行,但是不释放锁,信息依然不共享。
join()等待线程结束,如果在ThreadA中调用threadB.join()则ThreadA的thread.join()后面的程序要等到threadB结束后才运行。是fork-join的主要实现方法。
get/setPriority()设置优先级
线程同步:
关键字synchronizd,如果某个static方法要锁,则给整个类加锁,如果是给某个对象实例的某个代码块加锁,则给对象加锁。
感觉最重要的:显示加锁以下给出书上的消费生产者实例
public class threadTest {
private static Buffer buffer = new Buffer();
public static void main(String[] args) {
/*建立线程池
* 线程池用于管理并发执行任务个数的方法
* newFixed池如果任务超过规定的上线,则新的线程等待之前的任务执行完毕*/
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.execute(new ProducerTask());
executorService.execute(new ConsumerTask());
executorService.shutdown();
}
static class ProducerTask implements Runnable{
@Override
public void run() {
try {
int i=1;
while (true){
System.out.println("Producer writes "+i);
buffer.write(i++);
Thread.sleep((int)(Math.random()*10000));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class ConsumerTask implements Runnable{
@Override
public void run() {
try {
while (true){
System.out.println("\t\t\tConsumer reads"+buffer.read());
Thread.sleep((int)(Math.random()*10000));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Buffer{
//定义buffer的大小
private static final int CAPACITY = 1;
private LinkedList<Integer> queue = new LinkedList<>();
//创建一个新lock
private static Lock lock = new ReentrantLock();
private static Condition notEmpty = lock.newCondition();
private static Condition notFull = lock.newCondition();
public void write(int value){
lock.lock();
try {
while (queue.size()==CAPACITY){
//队列已满等待未满的信号来进行解锁进行下一步插入操作
System.out.println("Wait for notFull condition to insert");
notFull.await();
}
queue.offer(value);
//当前队列非空,释放当前队列非空信号,使下面的read操作可以执行下去
notEmpty.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}
finally {
lock.unlock();
}
}
public int read(){
int value = 0;
lock.lock();
try {
while (queue.isEmpty()){
System.out.println("\t\twait for notEmpty condition");
notEmpty.await();
}
value = queue.remove();
notFull.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}
finally {
lock.unlock();
return value;
}
}
}
}
lock和condition:
lock是锁住代码块的锁,condition是从lock中获取的标识,个人暂时理解为程序阻塞点的标识。
condition有如下方法:await()让程序阻塞,signal()唤醒同一个condition实例阻塞的程序,signalAll()唤醒同一个lock的所有condition实例。
Object的线程方法:
wait,notify,notifyAll,Object自带的原生方法,这些方法必须在实例的同步方法或者同步代码块中调用,具体效果类似于condition里面的wait和signal
死锁:
如下`thread1
synchronized(object1){
synchronized(object2){
}
thread2
synchronized(object2){
synchronized(object1){
}
}
即两个线程互相等待对方的锁。
避免死锁的方式:采用正确的资源排序避免死锁.