在千锋学习的第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();
}
}
}
}