面试题复习-java线程(一)
一、java 线程的创建方式
1.继承Thread类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class Demo extends Thread {
public static void main(String[] args) {
new Demo().start();
}
public void run() {
while (true) {
try {
Thread.sleep(100);
System.out.println(11);
} catch (Exception e) {
}
}
}
}2.实现runnable接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class Demo implements Runnable {
public static void main(String[] args) {
new Thread(new Demo()).start();
}
public void run() {
while (true) {
try {
Thread.sleep(100);
System.out.println(11);
} catch (Exception e) {
}
}
}
}3.使用lambda表达式(比较推荐这种方式)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32public class Demo {
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(100);
System.out.println(11);
} catch (Exception e) {
}
}
}
}).start();
}
}
public class Demo {
public static void main(String[] args) {
new Thread(() -> {
while (true) {
try {
Thread.sleep(100);
System.out.println(11);
} catch (Exception e) {
}
}
}).start();
}
}4.实现callable接口(可以拿到任务的结果)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public class Demo implements Callable<Integer> {
public static void main(String[] args) {
try {
// 创建FutureTask任务 优点可以拿到执行的结果
FutureTask<Integer> futureTask = new FutureTask<>(new Demo());
// 将FutureTask传给线程
Thread thread = new Thread(futureTask);
thread.start();
System.out.println(futureTask.get());
} catch (Exception e) {
e.printStackTrace();
}
}
public Integer call() throws Exception {
return 1;
}
}5.使用线程池创建线程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22public class Demo implements Runnable {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(new Demo());
}
public void run() {
try {
while (true) {
try {
Thread.sleep(100);
System.out.println(11);
} catch (Exception e) {
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}为什么不建议使用Executors来创建线程池
Executors的newFixedThreadPool构造方法如下:1
2
3
4
5public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}发现创建的队列为LinkedBlockingQueue,是一个无界阻塞队列,如果使用该线程池执行任务如果任务过多就会不断的添加到队列中,任务越多占用的内存就越多,最终可能耗尽内存,导致OOM。—OOM内存被使用完
对于 Executors的newSingleThreadExecutor构造方法如下:1
2
3
4
5
6
7public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory));
}同样也是LinkedBlockingQueue队列,会造成OOM内存消耗殆尽的事故
总结
除开有可能造成OOM之外,我们使用Executors来创建线程池也不能自定义现成的名字,不利于排查问题,所以建议直接使用ThreadPoolExecutor来定义线程池,可以灵活的来控制线程。
二、线程池有那些状态
RUNNING
Accept new tasks and process queued tasks
表示线程池正常运行,既能够接受新的任务,也会正常处理队列中的任务。SHUTDOWN
Don’t accept new tasks,but process queued tasks
当调用线程池的shutdown()方法时,线程池就会进入SHUTDOWN状态,表示线程池处于正在关闭状态,此状态下线程池不会接受新的任务,但是会继续把队列中的任务处理完毕。STOP
Don’t accept new tasks, don’t process queued tasks, and interrupt in-progress tasks
当调用线程池的shutdownnow()方法时,线程池就进入STOP状态,表示线程池处于正在停止状态,此状态下线程池既不会接受新任务了,也不会处理队列中的任务,并且正在运行的线程也会被中断TIDYING
All tasks have terminated, workerCount is zero, the thread transitioning to state TIDYINGwill run the terminated0 hook method
线程池中没有线程在运行后,线程池的状态就会自动变为TIDYING,并且会调用terminated0,该方法是空方法,留给程序员进行扩展。TERMINATED
terminated() has completed
terminated()方法执行完之后,线程池状态就会变为TERMINATED
