责任链模式是将请求发送者与处理者之间的耦合关系降低的一种行为模式。如,在公司中,研发部部长申请一笔部门活动经费,按照公司规定,经费在5万元内研发总监签字即可,经费在5万元至10万元的需要总经理批准,经费在10万元至20万元之间的需要副总裁批准。
按照一般思维,研发部部长必须很熟悉公司规章制度,自行根据金额大小去找不同领导签字,这就无形中增加了额外工作负荷。现在公司开发了一套系统,申请人只需要将金额等基本申请信息填写好,录入系统,系统根据公司规则自动判断该发送到哪个领导审批,相应领导接收到申请后审批,并将审批结果反馈回来。这样申请人无需去额外学习复杂的公司制度,也不需要关心是谁处理了这个申请,申请人和审批领导实现了解耦,提高了效率。这套系统就充当了责任链。 (更多…)
《待续》
动态代理与静态代理最大的不同在于,动态代理中,代理类对象由JVM生成,不再需要我们自己编写代理类。
核心实现:
1. java.lang.reflect.Proxy类动态生成代理类和对象,它提供用于创建动态代理类和实例的静态方法,是由这些方法创建的所有动态代理类的超类。
2.java.lang.reflect.InvocationHandler处理器接口,可以通过invoke方法实现对真实角色的访问。(每次通过Proxy生成代理类对象时都要指定该处理器接口) (更多…)
装饰模式的核心实现:
1.抽象组件(Component):具体类和装饰类基本功能规范,通过二者的实现,可以通过多态方式互为引用。
2.具体组件(Concrete Component):抽象组件的具体实现类。
3.抽象装饰(Decorator):继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
4.具体装饰(ConcreteDecorator):实现抽象装饰的相关方法,并给具体构件对象添加附加的功能。
下面以实例说明实现过程: (更多…)
一. java线程组特点:
1.所有用户创建的线程默认属于main线程组。main线程组是JVM在应用程序运行时自动创建。
2.如果线程A创建了线程B,创建时未指定线程组,那么线程组B自动加入线程A所在线程组。
3.线程一旦加入某个线程组,该线程就一直留着该组中,直至线程死亡,中途不可改变所属线程组。
4.用户创建的线程组默认都有一个父线程组。如线程A创建了线程组X,那么线程A所在线程组则默认称为线程组X的父线程组。
通过以下示例可验证:
package net.mosang.threadgroup; /** * 线程类 * @author Heiry * 模拟登录 */ public class SignUp implements Runnable{ private String userName; private String passWord; public SignUp(String userName, String passWord) { this.userName = userName; this.passWord = passWord; } @Override public void run() { System.out.println("你登录的用户名是:"+userName+"密码是:"+passWord); if(userName.equals("创建线程组")) { ThreadGroup tg = new ThreadGroup("newTg"); System.out.println("新线程内创建的线程组名是:"+tg.getName()); System.out.println("新线程内创建的线程组父线程组名是:"+tg.getParent().getName()); } } }
package net.mosang.threadgroup; /** * 线程组示例 * @author Heiry * */ public class ThreadGroupDemo { public static void main(String[] args) { SignUp u1 = new SignUp("heiry", "123"); SignUp u2 = new SignUp("mosang", "456"); Thread tu1 = new Thread(u1);//创建线程 Thread tu2 = new Thread(u2);//创建线程 System.out.println(tu1.getThreadGroup().getName());//输出“main”,tu1所属线程组 System.out.println(tu2.getThreadGroup().getName());//输出“main”, tu2所属线程组 ThreadGroup g1 = new ThreadGroup("用户线程组A");//创建线组,不指定父线程组 ThreadGroup g2 = new ThreadGroup("用户线程组B");//创建线组,不指定父线程组 Thread tu3 = new Thread(g1,u1);//创建线程,指定线程组 Thread tu4 = new Thread(g2,u2);//创建线程,指定线程组 System.out.println(tu3.getThreadGroup().getName());//输出“用户线程组A”,tu3所属线程组 System.out.println(tu4.getThreadGroup().getName());//输出“用户线程组B”, tu4所属线程组 System.out.println("g1父线程组是--->"+g1.getParent().getName()); // 输出“main” System.out.println("g2父线程组是--->"+g2.getParent().getName()); // 输出“main” SignUp u3 = new SignUp("创建线程组", "789");//线程内将创建线程组 Thread tu5 = new Thread(g1,u3);//创建线程,指定线程组 tu5.start(); } }
输出结果:
main main 用户线程组A 用户线程组B g1父线程组是--->main g2父线程组是--->main 你登录的用户名是:创建线程组密码是:789 新线程内创建的线程组名是:newTg 新线程内创建的线程组父线程组名是:用户线程组A
Callable 接口与Runnable接口类似可实现多线程的创建,但与Runnable不同的是,其线程方法call()有返回值并可抛出异常(Runnable 不会返回结果,并且无法抛出经过检查的异常)。另外Callable创建多线程依赖于线程池。
通过API查询,可以看到,Callable<V>是带泛型的,其泛型就是call方法返回值类型。
以下通过创建商品“秒杀”多线程FlashSale,实例讲解Callable 实现多线程的步骤:
1. 创建线程类FlashSale,实现Callable接口,重写call方法。
2.创建FlashSale线程实例binge,craze。
3.创建线程池对象实例shoppingPool
4.通过线程池实例shoppingPool的submit方法执行binge,craze。
package net.mosang.callabledemo; import java.util.concurrent.Callable; /** * FlashSale线程类 * @author Heiry * 重写不带任何参数的 call方法,返回String类型的抢购结果提示 */ public class FlashSale implements Callable<String>{ private String goodsName; @Override public String call() throws Exception { if(goodsName.equals("Mac电脑")) { return "抢到了苹果电脑"; }else if (goodsName.equals("Mi手机")) { return "抢到了小米手机"; } else { return "什么也没抢到"; } } public FlashSale(String goodsName) { super(); this.goodsName = goodsName; } }
package net.mosang.callabledemo; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; /** * * @author Heiry * */ public class Shopping { public static void main(String[] args) throws InterruptedException, ExecutionException { FlashSale binge = new FlashSale("Mac电脑"); //创建线程实例binge FlashSale craze = new FlashSale("Mi手机");//创建线程实例craze ExecutorService shoppingPool = Executors.newFixedThreadPool(2); Future<String> s1 = shoppingPool.submit(binge); Future<String> s2 = shoppingPool.submit(craze); System.out.println(s1.get()); System.out.println(s2.get()); } }
输出结果
抢到了苹果电脑 抢到了小米手机
可见,相比继承Thread与实现Runable接口方式实现多线程,Callable更方便地得到多线程的返回值并进行异常处理。另外,Callable依赖于线程池,通过此方式创建多线程,步骤繁琐,更适合处理高并发。