1 线程安全的第三种方法,Lock锁
package com.thread;
import java.util.concurrent.locks.ReentrantLock;
public class MyRunable implements Runnable {
private int ticket = 100;
ReentrantLock l=new ReentrantLock();
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
try {
l.lock();
Thread.sleep(10);
//在可能出現安全问题的代码处上锁
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "正在售" + ticket + "票");
ticket--;
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
l.unlock();
}
}
}
}
package com.thread;
public class ThreadProject {
public static void main(String[] args) {
MyRunable myrun=new MyRunable();
Thread t1=new Thread(myrun);
Thread t2=new Thread(myrun);
Thread t3=new Thread(myrun);
t1.start();
t2.start();
t3.start();
}
}
2 多个线程通信:等待唤醒机制
3 等待唤醒机制示例 : 顾客买包子与包子铺生产包子
这是对包子属性的封装
package com.stuffedSteamedBun;
/*
* 包子类
*/
public class StuffedSteamedBum {
public StuffedSteamedBum() {
}
public StuffedSteamedBum(String pi, String xian) {
this.pi = pi;
this.xian = xian;
}
//包子皮
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;
}
}
这是卖包子的消费者
package com.stuffedSteamedBun;
/*
* 消费者
*
*/
public class Consumer extends Thread {
public Consumer(StuffedSteamedBum baozi) {
this.baozi = baozi;
}
private StuffedSteamedBum baozi;
public void run(){
while(true){
synchronized(baozi){
if(baozi.isFlag()==false){
System.out.println("包子没有了,向包子铺要"+"包子");
try {
baozi.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("正在吃"+baozi.getPi()+baozi.getXian()+"的包子");
baozi.setFlag(false);
System.out.println("吃完"+baozi.getPi()+baozi.getXian()+"的包子了");
System.out.println("----------------------------------------------");
baozi.notify();
}
}
}
}
这是包子铺
package com.stuffedSteamedBun;
/*
* 包子铺
* 生产两种包子
*
*/
public class SteamedStore extends Thread {
public SteamedStore(StuffedSteamedBum baozi) {
this.baozi = baozi;
}
private StuffedSteamedBum baozi;
public void run() {
while (true) {
int count = 0;
// 同步代码块
synchronized (baozi) {
if (baozi.isFlag() == true) {
try {
baozi.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (count % 2 == 0) {
baozi.setPi("薄皮");
baozi.setXian("韭菜鸡蛋馅");
System.out.println("正在蒸" + baozi.getPi() + baozi.getXian() + "包子");
} else {
baozi.setPi("薄皮");
baozi.setXian("鲜肉馅");
System.out.println("正在蒸" + baozi.getPi() + baozi.getXian() + "包子");
}
baozi.setFlag(true);
System.out.println("包子好了,可以吃了");
baozi.notify();
}
}
}
}
主函数调用
package com.stuffedSteamedBun;
public class MainProduct {
public static void main(String[] args) {
//创建包子对象
StuffedSteamedBum baozi=new StuffedSteamedBum();
//创建包子铺线程,匿名对象
new SteamedStore(baozi).start();
//创建顾客线程,匿名对象
new Consumer(baozi).start();
}
}
4 线程池:
使线池的步骤
1. 使用线程池的工厂类Executors里面提供的静态方法newFixedThreadPool生产一个指定数量的线程池。
2.创建一个类,实现Runnable接口,重写run方法,设置线程任务
3.调用ExcutorService中的方法submit,传递线程任务(实现类),开启线程,执行run方法
4.调用ExcutorService中的方法shutdown销毁线程池(不建议执行)。
实例:使用线程池的工厂类Executors里面提供的静态方法newFixedThreadPool生产一个指定数量的线程池。调用ExcutorService中的方法submit,传递线程任务(实现类),开启线程,执行run方法
package com.threadPool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPool {
public static void main(String[] args) {
// TODO Auto-generated method stub
ExecutorService es=Executors.newFixedThreadPool(2);
es.submit(new MyRunable());
es.submit(new MyRunable());
es.submit(new MyRunable());
es.submit(new MyRunable());
//销毁线程池,不建议使用
//es.shutdown();
}
}
创建一个类,实现Runnable接口,重写run方法,设置线程任务
package com.threadPool;
public class MyRunable implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("当前线程的名字是"+Thread.currentThread().getName());
}
}