1. java 中的多线程设计模式有哪些?java
答: 单例模式,不变类,Future,生产消费者设计模式
2. 比较好的单例模式安全
2.1 线程安全且 具备懒加载的单例,缺点:性能不太好多线程
public class LazySingleton { private LazySingleton() { System.out.println("LazySingleton is create"); } private static LazySingleton instance = null; public static synchronized LazySingleton getInstance() { if (instance == null) instance = new LazySingleton(); return instance; } }
2.2 高性能,懒加载,且没有线程安全问题(使用内部类建立)app
public class StaticSingleton { private StaticSingleton(){ System.out.println("StaticSingleton is create"); } private static class SingletonHolder { private static StaticSingleton instance = new StaticSingleton(); } public static StaticSingleton getInstance() { return SingletonHolder.instance; } }
3. 不变模式异步
特色:一个类的内部状态建立后,在整个生命期间都不会发生变化时,就是不变类 性能
不变模式不须要同步this
public final class Product { //确保无子类 private final String no; //私有属性,不会被其余对象获取 private final String name; //final保证属性不会被2次赋值 private final double price; public Product(String no, String name, double price) { //在建立对象时,必须指定数据 super(); //由于建立以后,没法进行修改 this.no = no; this.name = name; this.price = price; } public String getNo() { return no; } public String getName() { return name; } public double getPrice() { return price; } }
4. Future异步加载模式spa
总结:调用客户端得到数据,生成一个壳子并返回(此时调用壳子的获取数据方法会阻塞),同时开启线程装配数据,完成以后注入到 壳子中,并通知线程返 回结果线程
效果:第一次要数据的时候返回一个壳子,用户拿着壳子获取数据时,若此时数据没装好,就会阻塞
3.1
public interface Data { public String getResult (); }
3.2
public class FutureData implements Data { protected RealData realdata = null; //FutureData是RealData的包装 protected boolean isReady = false; public synchronized void setRealData(RealData realdata) { if (isReady) { return; } this.realdata = realdata; isReady = true; notifyAll(); //RealData已经被注入,通知getResult() } public synchronized String getResult() { //会等待RealData构造完成 while (!isReady) { try { wait(); //一直等待,知道RealData被注入 } catch (InterruptedException e) { } } return realdata.result; //由RealData实现 } }
3.3
public class RealData implements Data { protected final String result; public RealData(String para) { //RealData的构造可能很慢,须要用户等待好久,这里使用sleep模拟 StringBuffer sb=new StringBuffer(); for (int i = 0; i < 10; i++) { sb.append(para); try { //这里使用sleep,代替一个很慢的操做过程 Thread.sleep(100); } catch (InterruptedException e) { } } result =sb.toString(); } public String getResult() { return result; } }
3.4
public class Client { public Data request(final String queryStr) { final FutureData future = new FutureData(); new Thread() { public void run() {// RealData的构建很慢, //因此在单独的线程中进行 RealData realdata = new RealData(queryStr); future.setRealData(realdata); } }.start(); return future; // FutureData会被当即返回 } }
3.5 使用该组件:
public static void main(String[] args) { Client client = new Client(); //这里会当即返回,由于获得的是FutureData而不是RealData Data data = client.request("name"); System.out.println("请求完毕"); try { //这里能够用一个sleep代替了对其余业务逻辑的处理 //在处理这些业务逻辑的过程当中,RealData被建立,从而充分利用了等待时间 Thread.sleep(2000); } catch (InterruptedException e) { } //使用真实的数据 System.out.println("数据 = " + data.getResult()); }
4. 生产消费者模式