创建线程的日常错误说法
所谓错误说法,并不是说方法就是错误的;只是相对于实现Runnable()接口和继承Thread类来说,这些都不是新的创建线程的方式。
- 线程池创建多线程
//线程池方式创建多线程
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 1000; i++) {
executorService.submit(new Task() {
});
}
}
static class Task implements Runnable{
@Override
public void run() {
try {
Thread.sleep(5000);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
复制代码
解答:
利用线程池方式创建多线程并非新的创建方式,究其本质,线程池需要一个线程工厂创建线程,线程工厂创建线程用的还是new 一个 Thread并传入Runnable方法。
//Executors源码
static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = "pool-" +
poolNumber.getAndIncrement() +
"-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
复制代码
2.无返回值是实现runnable接口,有返回值是实现callable接口,所以callable是新的实现线程方式
public static void main(String[] args) throws Exception {
FutureTask futureTask = new FutureTask(new MyThread());
new Thread(futureTask).start();
System.out.println("【数据返回】"+ futureTask.get());
}
static class MyThread implements Callable<String>{
@Override
public String call() throws Exception {
for (int i = 0; i < 100; i++) {
System.out.println("线程执行 + "+i);
}
return "多线程返回真牛逼";
}
}
复制代码
源码解答:
FutureTask类实现了RunnableFuture接口,然后RunnableFuture接口继承自Runnable接口和Future接口;其中Runnable接口负责Run方法,Future接口负责get方法返回;究其本质,还是创建了一个Thread类并传入Runnable实现多线程 3.计时器创建线程
public static void main(String[] args) {
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
},1000,1000);
}
复制代码
源码解答:
TimerTask类实现了Runnable对象,究其本质,还是Runnable对象
- 匿名内部 包装都没有,只是语法层面上的转换
- lambda 包装都没有,只是语法层面上的转换
关于停止线程的正确方式————常见面试题
- 如何停止线程
- 原理:用interrupt请求、好处 → 可以保证数据安全等等,把主动交给被中断的线程
- 想停止线程,要请求方、被停止方、子方法(优先抛出异常配合处理,或者捕获收到中断信号后再次设为中断状态)被调用方相互配合
- 最后再说错误的方法:stop/suspend已废弃,volatile的boolean无法处理长时间的阻塞情况
- 如何处理不可中断 的阻塞
如果线程阻塞是因为由于调用了wait()、sleep()或join()方法,你可以中断线程,通过抛出InterruptedException异常来唤醒该线程。 但是对于不能响应InterruptedException的阻塞,很遗憾,并没有一个通用的解决方案,但是我们可以利用特定的其他可以响应中断的方法。比如 ReentrantLock.lockInterruptibly(),比如关闭套接字使线程立即返回等方法来达到目的。 答案有很多种,因为有很多原因会导致线程阻塞,所以针对不同的情况,唤起的方法也不同。
作者:Jayhaw_花
链接:https://juejin.cn/post/6994075101259890724
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
本文暂时没有评论,来添加一个吧(●'◡'●)