多线程的第二篇文章,两个线程之间的通信就不写了,主要写写多个线程之间的通信和几个简单的设计模式吧。
一:多个线程的通信
以前的多线程之间的通信用wait()方法和while循环,配上notifyAll()方法,在jdk1.5的时候有了新改动,
同步:使用ReentrantLock的lock()和unlock()方法进行同步。
通信:使用ReentrantLock的newCondition()方法获取不同的condition对象,await()方法等待,signal唤醒指定的线程。
await后,后面的代码会暂时不执行(阻塞),直到有调用signal方法唤醒。
package S2;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class NotifyDemo2 {
/**
* 等待 唤醒机制。
*
* @param args
*/
public static void main(String[] args) {
final Printer2 p = new Printer2();
new Thread() {
public void run() {
while (true) {
try {
p.print1();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
new Thread() {
public void run() {
while (true) {
try {
p.print2();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
new Thread() {
public void run() {
while (true) {
try {
p.print3();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
}
}
/**
* wait方法可以传入参数也可以不传入 wait方法和sleep方法的区别就是 sleep方法在同步方法代码块中 不释放锁睡着了也抱着,
* wait方法在同步方法和同步代码块中 释放锁。
*
* @author xiaoning
*
*/
class Printer2 {
private ReentrantLock r = new ReentrantLock();
private Condition c1 = r.newCondition();
private Condition c2 = r.newCondition();
private Condition c3 = r.newCondition();
// 如果if换成while循环 所有线程都会进入等待状态 什么对象当做锁就用什么对象调用 wait notify方法
private int is = 1;
public void print1() throws Exception {
r.lock(); // 获取锁
if (is != 1) { // 最后 没有满足if条件 执行后面的字 之后is=2 唤醒2, 2会直接输出后面的字,
// 同样的道理 is=3 3会直接醒来输出后面的字在while循环所以会不停打印
c1.await();
}
System.out.print("人");
System.out.print("间");
System.out.print("天");
System.out.print("堂");
System.out.print("\r\n");
is = 2;
c2.signal();
r.unlock(); // 释放锁
}
public void print2() throws Exception {
r.lock();
if (is != 2) { // 例子: 假设首先2 != 1 线程2 在此等待
c2.await();
}
System.out.print("十八");
System.out.print("层");
System.out.print("地");
System.out.print("狱");
System.out.print("\r\n");
is = 3;
c3.signal();
r.unlock();
}
public void print3() throws Exception {
r.lock();
if (is != 3) { // 其次 线程 3!= 1 线程2 在此等待
c3.await(); // if循环是在哪等待就在哪起来
// while循环是循环判断 每次都会判断标记== ?
}
System.out.print("深");
System.out.print("山");
System.out.print("老");
System.out.print("林");
System.out.print("\r\n");
is = 1;
c1.signal(); // 唤醒指定的线程
r.unlock();
}
}
运行结果:
一:简单的几个设计模式
(1) 单例模式:
package S2;
public class SingleDemo {
public static void main(String[] args) {
Singledemo s1 = Singledemo.getIntence();
}
}
/**
* 恶汉式 单例 耗费空间节省时间
* @author xiaoning
*
*//*
class Singledemo {
private Singledemo() {// 私有构造方法,其他类不能访问
}
private static Singledemo s = new Singledemo();
public static Singledemo getIntence() {
return s;
}
}*/
/**
* 懒汉式单例 耗费时间 节省空间
* @author xiaoning
*
*/
class Singledemo {
private Singledemo() {// 私有构造方法,其他类不能访问
}
private static Singledemo s;
public static Singledemo getIntence() {
if(s==null){//不好 容易创建多个对象,当线程一进来了,执行权被线程二抢去了,线程二也进来了。。。。之后创建了多个对象
s = new Singledemo();
}
return s;
}
}
/**
* 懒汉式是时间换空间,恶汉式是空间换时间
* 在多线程模式中,懒汉式可能会创建多个对象,恶汉式不会创建多个对象。
* public static final Singledemo s ;
*/
(2)适配器模式:
package S2;
public class AdapterDemo {
/** 什么·是适配器? 在用监听器的时候 需要自定义一个事件监听接口, 监听器有很多方法,
* 有时候实现接口这么多方法,只需要重写用到的方法 此时用到适配器设计模式
* 适配器原理:是实现了监听器的接口,重写了所有方法,但是空的 ,定义监听器只需要重写其适配器的有用防范就行了
* 适配器设计模式 继承适配器,重写方法
* 事件:用户的操作
* 事件源:被操作的组件
*/
public static void main(String[] args) {
dog d = new dog();
d.run();
}
}
interface animal{
public abstract void say();
public abstract void walk();
public abstract void run();
}
abstract class animalson implements animal{ //abstract 不让其他类创建对象,创建也没有意义 ,方法都是空的 过渡
@Override
public void say() {
// TODO Auto-generated method stub
}
@Override
public void walk() {
// TODO Auto-generated method stub
}
@Override
public void run() {
// TODO Auto-generated method stub
}
}
class dog extends animalson{ //想重写那个方法就重写那个方法
@Override
public void run() {
super.run();
System.out.println("狗在跑。。。。。。");
}
}
()3工厂模式:
工厂方法模式概述
* 工厂方法模式中抽象工厂类负责定义创建对象的接口,具体对象的创建工作由继承抽象工厂的具体类实现。
* B:优点
* 客户端不需要在负责对象的创建,从而明确了各个类的职责,如果有新的对象增加,只需要增加一个具体的类和具体的工厂类即可,不影响已有的代码,后期维护容易,增强了系统的扩展性
* C:缺点
* 需要额外的编写代码,增加了工作量
* D:案例演示
*
动物抽象类:public abstract Animal { public abstract void eat(); }
工厂接口:public interface Factory {public abstract Animal createAnimal();}
具体狗类:public class Dog extends Animal {}
具体猫类:public class Cat extends Animal {}
开始,在测试类中每个具体的内容自己创建对象,但是,创建对象的工作如果比较麻烦,就需要有人专门做这个事情,所以就知道了一个专门的类来创建对象。发现每次修改代码太麻烦,用工厂方法改进,针对每一个具体的实现提供一个具体工厂。
狗工厂:public class DogFactory implements Factory {
public Animal createAnimal() {…}
}
猫工厂:public class CatFactory implements Factory {
public Animal createAnimal() {…}