Java 之多线程基础
1. 什么是多线程?
多线程是指在单个程序中同时执行多个任务。就像一个家庭,多个家庭成员可以同时进行不同的活动,比如做饭、洗衣服、看电视等等。
生活中的例子:
-
浏览器同时打开多个网页,每个网页都运行在独立的线程中。
-
手机同时运行着多个应用程序,比如音乐播放器、导航软件和聊天软件等等,这些应用都运行在不同的线程中。
2. 并行和并发
-
并发:是指多个任务在同一时间段内进行,但是可能不是真正同时执行,而是通过时间片轮流执行。就像一个厨师,可以同时炒菜和煮汤,但实际操作上是先炒菜几分钟,然后再去煮汤几分钟,不断切换。
-
并行:是指多个任务在同一时间点同时执行,需要多个处理器才能实现。就像两个人一起做菜,一个炒菜,一个煮汤,真正的同时进行。
生活中的例子:
-
并发:一台单核电脑,可以同时运行多个程序,但是实际上是操作系统将CPU时间分配给不同的程序,轮流执行。
-
并行:一台多核电脑,可以同时运行多个程序,每个程序都运行在不同的处理器上,真正同时执行。
3. 进程和线程
-
进程:是操作系统分配资源的最小单位,包含程序代码、数据和系统资源等。可以理解为一个独立运行的程序,比如浏览器、音乐播放器等等。
-
线程:是进程中的一个执行单元,共享进程的资源,是CPU调度和执行的最小单位。可以理解为一个进程中的一个任务,比如浏览器中的多个网页、音乐播放器中的播放和暂停等。
区别:
-
进程独立运行,拥有自己的内存空间,线程共享进程的内存空间。
-
进程之间通信相对困难,线程之间通信比较容易。
-
进程切换开销大,线程切换开销小。
4. 实现线程的四种方式
4.1 继承 Thread 类:
public class MyThread extends Thread {@Overridepublic void run() {System.out.println("我是线程:" + Thread.currentThread().getName());}public static void main(String[] args) {MyThread thread = new MyThread();thread.setName("线程1");thread.start();}
}
4.2 实现 Runnable 接口:
public class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("我是线程:" + Thread.currentThread().getName());}public static void main(String[] args) {MyRunnable runnable = new MyRunnable();Thread thread = new Thread(runnable, "线程2");thread.start();}
}
4.3 实现 Callable 接口:
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;public class MyCallable implements Callable<String> {@Overridepublic String call() throws Exception {return "我是线程:" + Thread.currentThread().getName();}public static void main(String[] args) throws Exception {MyCallable callable = new MyCallable();FutureTask<String> futureTask = new FutureTask<>(callable);Thread thread = new Thread(futureTask, "线程3");thread.start();System.out.println(futureTask.get());}
}
4.4 使用线程池:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPool {public static void main(String[] args) {ExecutorService executor = Executors.newFixedThreadPool(2);executor.execute(() -> System.out.println("我是线程:" + Thread.currentThread().getName()));executor.shutdown();}
}
四种方式的异同和优缺点:
方式 | 优点 | 缺点 |
继承 Thread 类 | 代码简洁 | 无法继承其他类 |
实现 Runnable 接口 | 可继承其他类 | 代码略复杂 |
实现 Callable 接口 | 可返回结果 | 代码略复杂 |
线程池 | 管理线程,提高效率 | 使用相对复杂 |
5. 线程休眠、优先级和守护线程
5.1 线程休眠:
-
概念:让线程暂停一段时间,让其他线程运行。
-
方法:Thread.sleep(long millis)
-
示例:
public class SleepThread extends Thread {@Overridepublic void run() {for (int i = 0; i < 5; i++) {System.out.println("我是线程:" + Thread.currentThread().getName() + ",i = " + i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
5.2 线程优先级
-
概念:设置线程的优先级,优先级高的线程更容易获得CPU时间片。
-
方法:Thread.setPriority(int priority),优先级范围为 1(最低)到 10(最高),默认5。
-
示例:
public class PriorityThread extends Thread {@Overridepublic void run() {for (int i = 0; i < 5; i++) {System.out.println("我是线程:" + Thread.currentThread().getName() + ",i = " + i);}}
}public class PriorityTest {public static void main(String[] args) {PriorityThread thread1 = new PriorityThread();thread1.setName("线程1");thread1.setPriority(Thread.MIN_PRIORITY);PriorityThread thread2 = new PriorityThread();thread2.setName("线程2");thread2.setPriority(Thread.MAX_PRIORITY);thread1.start();thread2.start();}
}
5.3 守护线程:
-
概念:守护线程是为其他线程服务的,当所有用户线程都结束时,守护线程也会自动结束。
-
方法:Thread.setDaemon(true)
-
示例:
public class DaemonThread extends Thread {@Overridepublic void run() {while (true) {System.out.println("我是守护线程,正在运行...");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}public class DaemonTest {public static void main(String[] args) {DaemonThread daemonThread = new DaemonThread();daemonThread.setDaemon(true);daemonThread.start();System.out.println("我是主线程,即将结束...");try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}
}
总结:
多线程是Java程序中重要的并发机制,可以提高程序效率,实现更复杂的应用。了解并行和并发、进程和线程的区别、实现线程的四种方式以及线程相关的概念,如休眠、优先级和守护线程,是学习Java多线程的基础。希望对各位看官有所帮助,感谢各位看官的观看,也祝大家今天中秋快乐,下期见,谢谢~