新建線程的方法有三種
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){
}
}
即兩個線程互相等待對方的鎖。
避免死鎖的方式:採用正確的資源排序避免死鎖.