JAVA面试十分钟-多线程

1.创建线程的方式

1.1 继承Thread类

public class ThreadTest extends Thread{
    @Override
    public void run() {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10000000; i ++) {
            list.add(i);
        }
        String name = Thread.currentThread().getName();
        System.out.println(name + ":" + list.size());
    }
}

执行

public static void threadRun() {
        ThreadTest threadTest = new ThreadTest();
        threadTest.start();
        ThreadTest threadTest2 = new ThreadTest();
        threadTest2.start();
        ThreadTest threadTest3 = new ThreadTest();
        threadTest3.start();
    }

1.2 继承Runnable接口

public class RunnableTest implements Runnable{
    @Override
    public void run() {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10000000; i ++) {
            list.add(i);
        }
        String name = Thread.currentThread().getName();
        System.out.println(name + ":" + list.size());
    }
}

执行

public static void runnableRun() {
        RunnableTest runnableTest = new RunnableTest();
        Thread thread = new Thread(runnableTest);
        Thread thread2 = new Thread(runnableTest);
        Thread thread3 = new Thread(runnableTest);
        thread.start();
        thread2.start();
        thread3.start();
    }

1.3 使用CompletableFuthur

无返回值

CompletableFuture.runAsync(() -> {
            List<Integer> list = new ArrayList<>();
            for (int i = 0; i < 100000; i ++) {
                list.add(i);
            }
            String name = Thread.curren`在这里插入代码片`tThread().getName();
            System.out.println(name + ":" + list.size());
        });

有返回值

CompletableFuture<String> uCompletableFuture = CompletableFuture.supplyAsync(() -> {
            return "abc";
        });
        uCompletableFuture.get();

指定线程池

 CompletableFuture.runAsync(() -> {
            List<Integer> list = new ArrayList<>();
            for (int i = 0; i < 100000; i ++) {
                list.add(i);
            }
            String name = Thread.currentThread().getName();
            System.out.println(name + ":" + list.size());
        }, Executors.newFixedThreadPool(4));

1.4 其他方式

此外,我们还可以通过实现Callable接口 与Future配合使用,以及使用线程池来获取线程,这里就不详细说明了。以上三种方式足可以应付面试。

2.守护线程

所谓守护线程是指在程序运行的时候在后台提供一种通用服务的线程,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止。

public class DaemonTest extends Thread{
    @Override
    public void run() {
        System.out.println("守护线程执行");
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 50; i ++) {
            list.add(i);
            System.out.println("守护线程" + ":" + list.size());
        }
		System.out.println("守护线程执行完毕!");
    }
}
public static void daemonRun() {

        ThreadTest threadTest = new ThreadTest();
        threadTest.start();
        DaemonTest daemonTest = new DaemonTest();
        daemonTest.setDaemon(true);
        daemonTest.start();

    }

我们利用上面的多线程例子,首先将计数器的次数都改为50,当一个正常的计数线程运行时,同时也运行一个守护线程,看看会发生什么

Thread-0:50
守护线程执行
守护线程:1
守护线程:2
守护线程:3

可以看到,守护线程并没有执行完,而是在正常计数器遍历完后关闭
再修改一下正常计数器,使次数改为100000,守护线程的次数仍然为50,看看会发生什么

守护线程执行
守护线程: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
守护线程:32
守护线程:33
守护线程:34
守护线程:35
守护线程:36
守护线程:37
守护线程:38
守护线程:39
守护线程:40
守护线程:41
守护线程:42
守护线程:43
守护线程:44
守护线程:45
守护线程:46
守护线程:47
守护线程:48
守护线程:49
守护线程:50
守护线程执行完毕!
Thread-0:100000

可以看到,守护线程在正常线程结束前结束
由此可见,守护线程和正常线程会同时运行,守护线程可以先于正常线程结束,但是如果正常线程运行结束,那么jvm绝对不会等待守护线程结束。

3.控制线程的执行顺序

使用jion方法,让主线程等待子线程结束以后才能继续运行,因此保证了线程的顺序执行。
使用wait-notify/notifyAll方法,对线程进行等待和唤醒,从而控制线程的执行顺序

发布了17 篇原创文章 · 获赞 1 · 访问量 3140

猜你喜欢

转载自blog.csdn.net/chouyiqiong5655/article/details/104146490