在千鋒學習的第29天
努力努力在努力,堅持堅持再堅持!!!加油
今天我學習了線程的死鎖,生產者和消費者,還有線程池,callable接口future接口和同步異步
C
第一個錯:主函數中t1不是線程他是一個任務類對象,要把t1傳入新new的線程如:Thread t3 = new Thread(t1);
第二個錯:MyThread1類的run方法中this.sleep()是不存在的,以爲Mythread1是實現的Runnable接口,沒有sleep這個方法,所以要修改爲Thread.sleep()然後要用try-catch語句處理Thread.sleep()異常,
第三個錯誤:MyThread2類中run方法不能聲明異常,要用try-catch語句處理this.sleep()異常,
死鎖問題:
package com.qf.day29.t2.questions;
public class TestDeadLock {
public static void main(String[] args) {
LeftChopstick lef = new LeftChopstick();
RightChopstick rig = new RightChopstick();
Thread boy = new Thread(new Boy(lef,rig),"男孩");
Thread girl = new Thread(new Girl(lef,rig),"女孩");
boy.start();
girl.start();
}
}
class LeftChopstick{
String name = "左筷子";
}
class RightChopstick{
String name = "右筷子";
}
class Boy implements Runnable{
LeftChopstick le;
RightChopstick ri;
public Boy(LeftChopstick le, RightChopstick ri) {
super();
this.le = le;
this.ri = ri;
}
@Override
public void run() {
synchronized (le) {//拿到左筷子資源,加鎖!
System.out.println(Thread.currentThread().getName() + "拿到左筷子");
try {
le.wait();//高風亮節!把筷子資源讓出去!
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (ri) {//拿到右筷子資源,加鎖!
System.out.println(Thread.currentThread().getName() + "拿到右筷子");
}
}
}
}
class Girl implements Runnable{
LeftChopstick le;
RightChopstick ri;
public Girl(LeftChopstick le, RightChopstick ri) {
super();
this.le = le;
this.ri = ri;
}
@Override
public void run() {
synchronized (ri) {//拿到右筷子資源,加鎖!
System.out.println(Thread.currentThread().getName() + "拿到右筷子");
synchronized (le) {//拿到左筷子資源,加鎖!
System.out.println(Thread.currentThread().getName() + "拿到左筷子");
le.notify();//女孩喫完後,喚醒等待左筷子鎖的男孩線程,如果不叫醒的話,男孩會一直在等沒有辦法回到競爭鎖隊列
}
}
}
}
死鎖總結:死鎖就是兩個線程訪問兩個對象,t1線程獲得了訪問A對象的鎖,t2線程獲得了訪問B對象的鎖,但是t1線程要想釋放A對象的鎖他必須要先得到B對象的鎖,而t2線程一樣要想釋放B對象的所就要先得到A對象的鎖,這樣就形成了雙方都沒辦法釋放鎖,僵局,解決辦法就是一方釋放當前鎖給另一方進入等待,然後另一方在釋放鎖之前,喚醒等待的一方進入爭搶鎖的隊列中
生產者和消費者
package com.qf.day29.t2.questions;
public class TestProductCustomer {
public static void main(String[] args) {
Shop shop = new Shop();//共享資源對象
Thread p = new Thread(new Product(shop),"生產者");
Thread c = new Thread(new Customer(shop),"消費者");
p.start();
c.start();
}
}
class Good{
int goodID;
public Good(int i){
this.goodID = i;
}
}
class Shop{
Good good;
boolean flag;//判斷超市是否需要補貨
//生產者訪問的方法
//shop對象給的鎖,他倆不能同時訪問
public synchronized void savaGood(Good good){
//判斷商品是否充足
if(flag == true){
System.out.println("滿貨中---------");
//怎麼判斷是誰調用的wait方法和notify方法,看線程的臨界資源是誰
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//商品不充足!生產者生產商品,存到商場裏
System.out.println(Thread.currentThread().getName()+"生產並在商場裏存放了"+good.goodID+"件商品");
this.good = good;
flag = true;//已經有商品了!可以讓消費者購買了!
//消費者等待。。。
this.notify();//將等待隊列的消費者喚醒!前來購買商品
}
//消費者調用的 取的方法
public synchronized void buyGoods() throws InterruptedException {
//判斷商品是否充足
if(flag == false){
System.out.println("缺貨中,等待中--------");
//怎麼判斷是誰調用的wait方法和notify方法,看線程的臨界資源是誰
this.wait();
}
//商品充足,消費者購買走了商品
System.out.println(Thread.currentThread().getName()+"買走"+good.goodID+"件商品");
this.good = null;
flag = false;//表示商品嗎,賣沒了缺貨了
//生產者等待。。。這時候生產者還在等待中
this.notify();//將等待隊列的生產者喚醒!去生產了
}
}
//生產者
class Product implements Runnable{
Shop shop;//商場
public Product(Shop shop) {
this.shop =shop;
}
@Override
public void run() {
//通過循環,生產商品存放到Shop裏
for(int i = 1 ;i <=30;i++){
//生產者線程調用存商品的方法。傳一個商品對象
this.shop.savaGood(new Good(i));
}
}
}
//消費者
class Customer implements Runnable{
Shop shop;//商場
public Customer(Shop shop) {
this.shop =shop;
}
@Override
public void run() {
for(int i = 1 ;i <=30;i++){
try {
this.shop.buyGoods();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}