多线程管理

细粒度

线程之间有同步协作

  • 等待
  • 通知/唤醒
  • 终止

线程状态

  • NEW 刚创建(new)
  • RUNNABLE 就绪态(start)
  • RUNNING 运行中(run)
  • BLOCK 阻塞(sleep)
  • TERMINATED 结束(terminated)

Thread的部分API已经废弃

  • 暂停和恢复suspend/resume
  • 消亡stop/destroy

线程阻塞/和唤醒

  • sleep,时间一到,自己会醒来
  • wait/notify/notifyAll,等待,需要别人来唤醒
  • join,等待另一个线程结束
  • interrupt,向另外一个线程发送中断信号,该线程接收到信息,会触发InterruptedException(可解除阻塞),并进行下一步处理

生产者消费者经典例子

消费者

package com.lihuan.thread.demo04;

public class Consumer implements Runnable{

    private Storage storage;

    public Consumer(Storage storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        int i = 0;
        while (i < 10){
            i++;
            storage.pop();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

生产者

package com.lihuan.thread.demo04;

import java.util.Random;

public class Producer implements Runnable{
    private Storage storage;

    public Producer(Storage storage){
        this.storage = storage;
    }

    @Override
    public void run() {
        int i = 0;
        Random r = new Random();
        while (i < 10) {
            i++;
            Product product = new Product(i, "电话" + r.nextInt(100));
            storage.push(product);
        }
    }
}

产品

package com.lihuan.thread.demo04;

public class Product {
    private int id;
    private String name;

    public Product() {
    }

    public Product(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Product{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

仓库

package com.lihuan.thread.demo04;

public class Storage {
    //厂库容量为10
    private Product[] products = new Product[10];
    private int top = 0;

    public synchronized void push(Product product){
        while (top == products.length){
            try {
                System.out.println("producer wait");
                wait();//厂库满了,等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //把产品放入仓库
        products[top++] = product;
        System.out.println(Thread.currentThread().getName() + " 生产了产品" + product);
        System.out.println("producer notifyAll");
        notifyAll();//唤醒等待线程
    }

    public synchronized Product pop() {
        while (top == 0) {
            try {
                System.out.println("consumer wait");
                wait();//仓库空,等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //把产品拿出仓库
        --top;
        Product p = new Product(products[top].getId(), products[top].getName());
        products[top] = null;
        System.out.println(Thread.currentThread().getName() + " 消费了产品" + p);
        System.out.println("consumer notifyAll");
        notifyAll();//唤醒等待线程
        return p;
    }
}

主类

package com.lihuan.thread.demo04;

/**
 * 经典生产者和消费者问题
 */
public class ProductTest {
    public static void main(String[] args) {
        Storage storage = new Storage();
        Thread consumer1 = new Thread(new Consumer(storage));
        consumer1.setName("消费者1");
        Thread consumer2 = new Thread(new Consumer(storage));
        consumer2.setName("消费者2");
        Thread producer1 = new Thread(new Producer(storage));
        producer1.setName("生产者1");
        Thread producer2 = new Thread(new Producer(storage));
        producer2.setName("生产者2");

        producer1.start();
        producer2.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        consumer1.start();
        consumer2.start();
    }
}

线程被动地暂停和终止

  • 依靠别的线程来拯救自己
  • 没有及时释放资源

线程主动暂停和终止

  • 定期监测共享变量
  • 如果需要暂停或者终止,先释放资源,再主动动作
  • 暂停:Thread.sleep(),休眠
  • 终止:run方法结束,线程终止

例子:

package com.lihuan.thread.demo04.interrupt;

public class InterruptTest {
    public static void main(String[] args) {
        TestThread1 t1 = new TestThread1();
        TestThread2 t2 = new TestThread2();

        t1.start();
        t2.start();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t1.interrupt();
        t2.flag = false;
        System.out.println("main thread is exiting");
    }
}
//被动
class TestThread1 extends Thread{
    @Override
    public void run() {
        while (!interrupted()){
            System.out.println("test thread1 is running");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
        System.out.println("test Thread1 is exiting");
    }
}
//主动
class TestThread2 extends Thread{
    public volatile boolean flag = true;

    @Override
    public void run() {
        while (flag){
            System.out.println("test thread2 is running");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("test thread2 is exiting");
    }
}

多线程死锁

  • 每个线程互相持有别人需要的锁(哲学家吃面问题)
  • 预防死锁,对资源进行等级排序
package com.lihuan.thread.demo04.deadlock;

import java.util.concurrent.TimeUnit;

public class ThreadDemo5 {
    public static Integer r1 = 1;
    public static Integer r2 = 2;

    public static void main(String[] args) {
        TestThread51 t1 = new TestThread51();
        t1.start();
        TestThread52 t2 = new TestThread52();
        t2.start();
    }
}
class TestThread51 extends Thread{
    @Override
    public void run() {
        synchronized (ThreadDemo5.r1){
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (ThreadDemo5.r2){
                System.out.println("TestThread51 is running");
            }
        }
    }
}
class TestThread52 extends Thread{
    @Override
    public void run() {
        synchronized (ThreadDemo5.r2){
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (ThreadDemo5.r1){
                System.out.println("TestThread52 is running");
            }
        }
    }
}

可以使用 jvisualvm (命令:线程查看工具)进行死锁的查看

守护(后台)进程

  • 普通线程的结束,是run方法运行结束
  • 守护线程的结束,是run方法运行结束,或main函数结束
  • 守护线程永远不要访问资源,如文件和数据库
package com.lihuan.thread.demo04.daemon;

public class ThreadDemo4 {
    public static void main(String[] args) {
        TestThread4 t = new TestThread4();
        t.setDaemon(true);//守护线程主线程结束,则该线程结束
        t.start();
        System.out.println("main thread is exiting");
    }
}

class TestThread4 extends Thread{
    @Override
    public void run() {
        while (true){
            System.out.println("TestThread4" + " is running");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值