Java线程,锁机制,生产者消费者以及线程池

一. Thread

第一种创建线程的方式(创建线程的子类)

  1. java.util.lang包下的
  2. 创建一个线程类继承Thread,要重写run方法
public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println(getName());
    }
}
  1. 调用start方法,抢夺cpu
Tread mt = new MyThread();
mt.start();//开始与主程序一起运行,抢夺cpu,执行run中的内容
  1. 匿名内部类
		new Thread(){
            @Override
            public void run() {
                for(int i = 0; i < 20; i++)
                {
                    System.out.println(Thread.currentThread().getName()+ "lwt");
                }
            }
        }.start();

第二种创建线程的方式(Runnable)

  1. 创建Runnable的实现类RunnableImpl,实现run方法
public class RunnableImpl implements Runnable {
    public void run() {
        System.out.println(Thread.currentThread().getName()+ "创建了一个新的线程");
    }
}

  1. 创建Runnable的实现类对象,创建Thread类对像并将Runnable的实现类对象传入构造函数中去
Runnable run = new RunnableImpl();
Thread thread = new Thread(run);
  1. 调用其start方法开始与主程序强夺cpu
thread.start();
  1. 匿名内部类
		Object object = new Object();
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized(object){
                    System.out.println("老板,来一个包子");
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("顾客:开吃");
                    System.out.println("-----------");
                }
            }
        }).start();

这种方法避免了单继承的局限性,解耦(增强拓展性)

Thread类的常用方法

1. String getName();
2. static Thread currentThread();
3. void setName("name");
4. 设置名字:创建带参数的构造方法
5. static void sleep(long mills)//休眠

二. 不同线程访问共享数据的解决办法

1. 同步代码块

  1. 锁对象可以是任意对象
  2. 必须保证多个线程使用的对象是同一个
  3. 锁对象的作用:同步代码块内部的内容锁住,只让一个线程在同步代码块里面执行
Object obj = new Object();//创建锁对象
synchronized (obj){
		//访问共享数据的代码
}

2. 同步方法

  1. 把访问方法了共享数据的代码抽取出来,放到一个方法中
  2. 方法添加一个synchronized的修饰符
  3. 在run中调用
public static synchronized void 方法名()
{
}

这个的锁对象其实是本类的class属性(如RunnableImpl.class)

3. Lock锁(两个方法)

  1. void lock() 锁上
  2. void unlock() 解锁
  3. Lock是一个接口,其中的一个实现类ReentrantLock
	private Lock lock = new ReentrantLock();
	public void run() {
        while (ticket > 0)
        {
            lock.lock();//锁上
           System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票");
            lock.unlock();//解锁
        }

    }

三. 线程状态

  1. Time_waiting(睡眠状态)
    这个用Thread.sleep()进入
  2. waiting(永久等待)
    object.wait()
    object.notify()

四. 进程间的通信,等待唤醒案例

  1. 同步代码块锁上控制资源,然后用wait,notify来控制进程
//Baozi.java
package practice.Demo05Thread;

public class Baozi {

    private String pi;
    private String xian;
    private boolean flag = false;

    public String getPi() {
        return pi;
    }

    public void setPi(String pi) {
        this.pi = pi;
    }

    public String getXian() {
        return xian;
    }

    public void setXian(String xian) {
        this.xian = xian;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}


//Baozipu.java
import java.util.concurrent.ThreadLocalRandom;

public class Baozipu extends Thread{
    private Baozi baozi;

    public Baozipu(Baozi baozi){
        this.baozi = baozi;
    }


    @Override
    public void run() {
        int count = 0;
        while (true)
        {
            synchronized (baozi)
            {

                if(baozi.isFlag())
                {
                    try {
                        //有包子就等待,不用包子
                        baozi.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                // 开始生产包子
                if(count % 2 == 0)
                {
                    //生产牛肉薄馅
                    baozi.setPi("薄皮");
                    baozi.setXian("牛肉");
                }else if(count % 2 == 1)
                {
                    baozi.setPi("厚皮");
                    baozi.setXian("葱花");
                }
                count++;

                System.out.println("包子铺正在生产: "+ baozi.getPi()+baozi.getXian() +"的包子");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                baozi.setFlag(true);
                //唤醒顾客吃包子
                baozi.notify();
            }
        }
    }
}


//Chihuo.java

public class Chihuo extends Thread {
    private Baozi baozi;

    public Chihuo(Baozi baozi)
    {
        this.baozi = baozi;
    }


    @Override
    public void run() {
        while(true)
        {
            synchronized (baozi)
            {
                if (!baozi.isFlag())
                {
                    try {
                        baozi.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                //现在有包子了,开始吃

                System.out.println("游客开始吃"+baozi.getXian()+baozi.getPi() + "的包子");

                baozi.setFlag(false);
                //唤醒包子铺做包子
                baozi.notify();
                System.out.println("游客已经吃完包子了");
            }
        }
    }
}


//Demo.java

package practice.Demo05Thread;

public class Demo {
    public static void main(String[] args) {
        Baozi baozi = new Baozi();

        new Baozipu(baozi).start();

        new Chihuo(baozi).start();
    }
}

五. 线程池

  1. 自从jdk1.5之后就提供线程池
  2. Java.util.concurrent.Executors中有一个静态方法
    Static ExecutorService newFixedThreadPool(int n)返回值一个实现类的对象
  3. 这个实现类对象含有的方法
    取出线程Thread t = ex.submit(Runnable Task)
    关闭线程池,不建议使用 void shutdown()
public static void main(String[] args) {
        ExecutorService ex = Executors.newFixedThreadPool(2);
        ex.submit(new RunnableImpl());
        ex.submit(new RunnableImpl());
        ex.submit(new RunnableImpl());
        ex.submit(new RunnableImpl());
		ex.shutdown()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值