java 线程工厂_【java吧】JAVA线程池之三,自定义线程工厂,扩展线程池以及Future...

Java concurrent in practice author:Brian Goetz / Tim Peierls / Joshua Bloch / Joseph Bowbeer / David Holmes / Doug Lea

还有很多地方需要深入研究以及没有理解到位的地方,但是我会尽最大的努力做到知识全面化,为大家带来更详细,更深入的知识,如果有那些地方您觉得不对,希望可以在评论区指出,小编会感激不尽!!!

在使用线程或者线程池尽量指定线程的名字便于问题回溯,那么在线程池之中可以通过实现ThreadFactory接口可以实现对线程池中线程的名称,ThreadGroup,线程的优先级,线程的守护状态比如是否为守护线程,我们使用了dubbo中线程工厂的实现进行解读

" d2 Q1 \4 R% K5 o412868061c65ed3fd0aab7e9fce64e08.png

% Y' M( z6 x" Z: S4 i. Q" D6 X3 P& y' S, a) }3 N

public class NamedThreadFactory implements ThreadFactory {    protected static final AtomicInteger POOL_SEQ = new AtomicInteger(1);    protected final AtomicInteger mThreadNum = new AtomicInteger(1);    protected final String mPrefix;    protected final boolean mDaemon;    protected final ThreadGroup mGroup;    public NamedThreadFactory() {        this("pool-" + POOL_SEQ.getAndIncrement(), false);    }    public NamedThreadFactory(String prefix) {        this(prefix, false);    }    public NamedThreadFactory(String prefix, boolean daemon) {        mPrefix = prefix + "-thread-";        mDaemon = daemon;        SecurityManager s = System.getSecurityManager();        mGroup = (s == null) ? Thread.currentThread().getThreadGroup() : s.getThreadGroup();    }    @Override    public Thread newThread(Runnable runnable) {        String name = mPrefix + mThreadNum.getAndIncrement();        Thread ret = new Thread(mGroup, runnable, name, 0);        ret.setDaemon(mDaemon);        return ret;    }    public ThreadGroup getThreadGroup() {        return mGroup;    }}

我们可以看到通过实现ThreadFactory中的newThread(Runnable runnable)方法,在通过重新构建线程的方式实现了线程信息的重构

扩展ThreadPoolExecutor线程池,线程池中提供了几个可以在子类中改写的方法分别是afterExecute,beforeExecute,terminated。在执行任务的多线程中将调用beforeExecute和afterExecute。可以用来添加日志,监控或者统计信息等。无论任务正常执行或者抛出异常afterExecute都会执行(返回Error异常除外),如果beforeExecute返回一个RuntimeException,则任务不会执行并且afterExecute方法也不会执行% h. q* ]* Q8 x, V4 v' g' x

public class MyThreadPoolExecutor extends ThreadPoolExecutor {    public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize,                                long keepAliveTime, TimeUnit unit, BlockingQueue workQueue,                                ThreadFactory threadFactory) {        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);    }    @Override    protected void afterExecute(Runnable r, Throwable t) {        System.out.println("afterExecute");        super.afterExecute(r, t);    }    @Override    protected void beforeExecute(Thread t, Runnable r) {        System.out.println("beforeExecute");        super.beforeExecute(t, r);    }    @Override    protected void terminated() {        super.terminated();    }}

Future和Callable 就像去市场订货,商家给了你收据,然后在未来的某个时刻你拿着收据来领货

线程池中除了可以提交Runnable对象之外,还可以提交Callable,Callable除了具备Runnable 对象的语义之外,Callable 可以提供返回值如果执行失败产生异常则返回.当提交Callable到线程池,线程池会返回Future对象,Callable和Future是一一对应的,Future中的get方法会返回Callable对象call方法执行的结果,但是这个get方法是阻塞方法,意味着这个方法是可以中断的

public interface Future {) t6 C9 E$ Z* D8 A

+ h2 x2 C  \9 X# \

V get( ) throws InterruptedException, ExecutionException;4 E# {- @4 N7 x4 K5 ?

/ b( X3 ]6 z6 `4 d7 A# }

V get(long timeout, TimeUnit unit)

7 U9 z, R! o5 M/ G" E

: g# ?+ g5 I  K6 {5 A. y

throws InterruptedException, ExecutionException,) F& |! ~/ o5 ^* `6 G

: t, L: k! k7 q8 b7 t

TimeoutException;" ]7 s% i; L) @0 y2 C) b$ Z' n- |

7 J7 ^0 |. s" i6 |( B

boolean isDone( );. L8 x8 b) n5 r; [6 @2 f

, T/ h9 g% e; D, G( ^/ U! c

boolean cancel(boolean mayInterruptIfRunning);

5 y  |. U4 j# u* Q

8 \  }0 u5 o9 c: \/ q& k; ~

boolean isCancelled( );

- [" R6 n# B5 ?8 H) }" X

, O/ o4 N" o2 `" }/ V7 J

}复制代码

0 g, ]2 |8 h+ J% I6 v, _" t; S

Future对象会持续追踪Callable对象的状态,状态来自于cancel()方法的调用,当调用cancel方法时call方法会检查当前的状态,如果是取消的状态,call方法会立即返回任务会取消.当任务已经执行完成则cancel()方法不会起任何作用。如果将cancel方法中的mayInterruptIfRunning设置为false,则任务不受任何影响,如果设置为true,则会将线程中断,可以调用Thread.interrupted方法监控中断状态.

我们直到callable对象是在线程池中执行的,所以如果调用cancel方法时,不会立即取消,我们知道callable对象可能在队列中,直到线程即将执行到取消的任务时,会检查任务状态,如果是取消的状态,则跳过此任务,所以取消的对象不会立即腾出空间,但是注意execute方法不会检查对象的状态

还有一种解决方案就是调用purge方法,purge方法会检查整个queue中已经取消的任务并且删除他们。

需要注意的是:如果第二个线程试图向池中添加某些内容(使用execute()方法)在第一个线程试图调用purge清除队列,那么清除队列的尝试失败,被取消的对象仍保留在排队。

一种比较好的方式是采用线程池中的remove方法,remove方法会立即删除在队列中的任务,但是只适用于Runnable对象

那么有没有办法能让Runnable对象可不可以像callable对象可以取消,获取返回值呢?

答案是有的 FutureTask 我们可以看到FutureTask既实现了Futrue也实现了Runnable

public class FutureTask implements Future, Runnable {}

execute方式调用futureTask+ c% _9 T8 x4 ]6 |+ ]6 Y' P

b906b2c1ff11c8f0238b7104145eea6d.png

4 M/ g; v0 `% i8 w/ }) S# j, h: p$ M0 T8 ^1 s' Y: [

& l! D1 g# y/ A' s' m$ D+ O

sumbit方式调用Futuretask7 N3 u0 O7 ]' d4 K3 H; ~% A/ ?; I

79f650c334059619919744d1752e41c5.png

# P: Y% d7 Y9 X0 ]: X8 k

1 p3 U) C/ |6 O; ?6 A! `# D

2 S: T5 _! ~- ?7 C$ h/ p  |7 P# I4 Pjava吧 java论坛

D( {2 T4 @1 F# Y

: w/ z: [, G6 i: O3 {) C; k$ f. O" \9 n" [: ?6 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值