01. java多线程

01.线程概念

线程就是独立的执行路径;
在程序运行时, 即使没有自己创建线程, 后台也会有多个线程, 如主线程, gc线程;
main()称之为主线程, 为系统的入口, 用于执行整个程序;
在一个进程中, 如果开辟了多个线程, 线程的运行由调度器安排调度, 调度器是与操作系统紧密相关的, 先后顺序是不能认为的干预的。
对同一份资源操作时, 会存在资源抢夺的问题, 需要加入并发控制;
线程会带来额外的开销, 如cpu调度时间, 并发控制开销。
每个线程在自己的工作内存交互, 内存控制不当会造成数据不一致

 02.创建方式

1)继承Thread类

1 public class MyThread extends Thread {
2     public void run(){
3         // 线程执行的代码
4     }
5 }
6  
7 // 使用
8 MyThread myThread = new MyThread();
9 myThread.start();

2)实现Runnable接口

1 public class MyRunnable implements Runnable {
2     public void run(){
3         // 线程执行的代码
4     }
5 }
6 // 使用
7 MyRunnable myRunnable = new MyRunnable();
8 Thread thread = new Thread(myRunnable);
9 thread.start();

3)实现Callable接口

 1 ExecutorService executorService = Executors.newCachedThreadPool();
 2         Future<String> future = executorService.submit(new Callable<String>() {
 3             public String call() throws Exception {
 4                 // 线程执行的代码
 5                 return "结果";
 6             }
 7         });
 8 
 9         try {
10             String result = future.get();
11         } catch (InterruptedException | ExecutionException e) {
12             // 处理异常
13         }
14         executorService.shutdown();

 03.线程join

在Java中,join方法是线程间同步的一种手段,它允许一个线程等待另一个线程完成后再继续执行。具体来说,当某个线程调用另一个线程的join方法时,调用线程会被阻塞,直到被join的线程执行完毕(即线程终止)为止。

class Worker extends Thread {
    private String name;

    Worker(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        try {
            System.out.println(name + " is starting.");
            for (int i = 0; i < 10; i++) {
                if ("Worker 2".equals(name)) {
                    Thread.sleep(1000);
                }
                System.out.println(name + " " + i);
                Thread.sleep(100); // 模拟一些工作
            }
            System.out.println(name + " is finished.");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Thread worker1 = new Worker("Worker 1");
        Thread worker2 = new Worker("Worker 2");
        worker1.start();
        worker2.start();
        try {
            System.out.println("Main thread is waiting for workers to finish.");
            worker1.join();
            System.out.println("All workers are finished. Main thread is continuing.");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
线程join

print:

Main thread is waiting for workers to finish.
Worker 2 is starting.
Worker 1 is starting.
Worker 1 0
Worker 1 1
Worker 1 2
Worker 1 is finished.
All workers are finished. Main thread is continuing.
Worker 2 0
Worker 2 1
Worker 2 2
Worker 2 is finished.
print

 

在这个示例中:

  1. 我们创建了两个Worker线程,每个线程都会在启动时打印一条消息,睡眠1秒钟(模拟工作),然后在结束时再打印一条消息。
  2. 在主线程中,我们启动了这两个Worker线程。
  3. 主线程调用worker1.join(),这会导致主线程等待worker1线程执行完毕后再继续执行,并不会等待worker2执行完毕。
  4. Worker1线程都执行完毕后,主线程会打印"All workers are finished. Main thread is continuing."。

04.线程状态

 05.守护线程

在Java中,守护线程(Daemon Thread)是一种特殊的线程,它的主要特点是:当JVM中不存在任何非守护线程(即用户线程)时,JVM会自动退出,不会等待守护线程执行完毕。守护线程通常用于为其他线程或系统提供服务,如垃圾回收线程、后台日志记录线程等。

要创建一个守护线程,可以通过调用Thread对象的setDaemon(true)方法来实现

 1 public class DaemonThreadExample {
 2     public static void main(String[] args) {
 3         Thread userThread = new Thread(new UserTask(), "UserThread");
 4         Thread daemonThread = new Thread(new DaemonTask(), "DaemonThread");
 5 
 6         // 将daemonThread设置为守护线程
 7         daemonThread.setDaemon(true);
 8 
 9         userThread.start();
10         daemonThread.start();
11 
12         // 主线程虽然执行完毕,但是程序不会退出,直到用户线程执行完毕才会退出,并不会等待守护线程执行完毕
13         System.out.println("Main thread is exiting...");
14     }
15 
16     static class UserTask implements Runnable {
17         @Override
18         public void run() {
19             try {
20                 for (int i = 0; i < 5; i++) {
21                     System.out.println(Thread.currentThread().getName() + " is running...");
22                     Thread.sleep(1000);
23                 }
24             } catch (InterruptedException e) {
25                 e.printStackTrace();
26             }
27             System.out.println(Thread.currentThread().getName() + " is finished.");
28         }
29     }
30 
31     static class DaemonTask implements Runnable {
32         @Override
33         public void run() {
34             try {
35                 while (true) {
36                     //一直在这里守护你,你不走,我不走
37                     System.out.println(Thread.currentThread().getName() + " is running in the background...");
38                     Thread.sleep(500);
39                 }
40             } catch (InterruptedException e) {
41                 e.printStackTrace();
42             }
43         }
44     }
45 }
守护线程测试

 

posted @ 2025-01-06 15:11  一品码农  阅读(12)  评论(0)    收藏  举报