进程与线程
进程:进程是程序的基本执行实体
线程:线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位
在Java中,进程(Process)和线程(Thread)是两个并发执行的概念,用于实现多任务处理和并发执行。它们都是操作系统和编程语言级别的概念,用于管理和执行程序的不同部分。
- 进程(Process): 进程是计算机中运行的程序的执行实例。每个进程都有自己的独立内存空间和系统资源,包括文件句柄、网络连接等。进程之间相互隔离,一个进程的崩溃通常不会影响其他进程。进程之间的通信通常需要使用特定的机制,如进程间通信(Inter-Process Communication,IPC)。在Java中,可以使用进程来执行不同的Java应用程序。
- 线程(Thread): 线程是在同一个进程内部运行的执行单元。一个进程可以包含多个线程,它们共享同一进程的内存空间和系统资源。由于线程共享内存,线程之间的通信和数据共享相对容易。但也正因为共享资源,需要特别注意线程安全问题,避免出现竞态条件等并发问题。在Java中,线程是通过Thread类或实现Runnable接口来创建的。
并发与并行
并发:在同一时刻,有多个指令在CPU上交替执行。
并行:在同一时刻,有多个指令在多个CPU上同时执行。
多线程实现的三个方式
1、继承Thread类
public class CreateThread extends Thread{
public static void main(String[] args) {
CreateThread createThread = new CreateThread();
CreateThread createThread2 = new CreateThread();
createThread.start();//开启线程
createThread2.start();//开启线程
// System.out.println(createThread.getName());
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName()+"--"+i);//注意在当前线程中可以直接使用当前线程的方法
}
}
}
从运行结果可以发现两个线程是交替执行的,运行结构如下图:
2、实现Runnable接口
public class CreateRunnable implements Runnable{
public static void main(String[] args) {
CreateRunnable runnable=new CreateRunnable();//创建CreateRunnable对象,表示多线程要执行的任务
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
Thread thread3 = new Thread(runnable);
thread1.start();
thread2.start();
thread3.start();
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
Thread thread = Thread.currentThread();//获取当前线程的对象
System.out.println(thread.getName()+"--"+i);//注意在当前线程中可以直接使用当前线程的方法
}
}
}
3、利用Callable接口和Future接口的方式实现
public class CreateCallable implements Callable<Integer> {
public static void main(String[] args) throws Exception {
CreateCallable callable1= new CreateCallable();//创建对象,创建执行的任务
CreateCallable callable2= new CreateCallable();
FutureTask<Integer> futureTask = new FutureTask<>(callable1);//创建FutureTask对象,管理多线成功运行的结构
Thread thread = new Thread(futureTask);//创建线程的对象,传入任务
thread.start();//启动线程
Integer o = futureTask.get();//获取线程的返回结果
System.out.println(o);
}
@Override
public Integer call() throws Exception {
for (int i = 0; i < 10; i++) {
Thread thread = Thread.currentThread();
System.out.println(thread.getName()+"--"+i);
}
return 1;
}
}
线程的方法
@Test
public void test2(){
Thread thread = Thread.currentThread();//获取当前线程对象
System.out.println(thread);
thread.setName("threadname");//设置线程名称
System.out.println(thread.getName());//获取当前线程名称
System.out.println(thread.getName());
}
守护线程
package com.xccvt.demo11_thread.method;
public class TestThread1 extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName()+" -- "+i);
}
}
}
package com.xccvt.demo11_thread.method;
public class TestThread2 extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+" -- "+i);
}
}
}
package com.xccvt.demo11_thread.method;
public class TestMethod {
public static void main(String[] args) {
TestThread1 testThread1 = new TestThread1();
TestThread2 testThread2 = new TestThread2();
//当其他的非守护线程执行完毕之后,守护线程会陆续结束,可以看到TestThread1执行完毕后,TestThread2陆续结束执行,TestThread2本来可以执行到99的
testThread2.setDaemon(true);//将线程testThread1设置为守护线程,
testThread1.setName("TestThread1");
testThread2.setName("TestThread2");
testThread1.start();
testThread2.start();
}
}
礼让线程
public class TestThread1 extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName()+" -- "+i);
Thread.yield();//设置礼让线程,设置后会停止此线程执行,重新选择分配线程
}
}
}
插入线程
@Test
public void test4() throws InterruptedException {
TestThread1 testThread2 = new TestThread1();
// testThread2.
testThread2.start();
testThread2.join();//把testThread2这个线程插入到当前线程之前执行
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+" -- "+i);
Thread.yield();//设置礼让线程,设置后会停止此线程执行,重新选择分配线程
}
}
线程的声明周期
常用方法
静态方法 | 描述 |
---|---|
currentThread() | 获取当前正在执行的线程对象。 |
sleep(long millis) | 使当前线程休眠指定的毫秒数。 |
yield() | 建议线程调度器将CPU时间让给其他线程。 |
interrupt() | 中断线程,设置线程的中断状态为true。 |
interrupted() | 测试当前线程是否被中断,并清除中断状态。 |
isInterrupted() | 测试线程是否被中断,不清除中断状态。 |
join() | 等待指定线程执行完毕,然后继续当前线程。 |
sleep(long millis, int nanos) | 使线程休眠指定的毫秒数和纳秒数。 |
activeCount() | 返回当前线程组中活动线程的估计数。 |
enumerate(Thread[] tarray) | 将当前线程组及其子组中的所有活动线程复制到数组。 |
setDefaultUncaughtExceptionHandler() | 设置默认未捕获异常处理程序。 |
getDefaultUncaughtExceptionHandler() | 获取默认未捕获异常处理程序。 |
方法 | 描述 |
---|---|
Thread类的构造方法: | |
Thread() | 创建一个新线程。 |
Thread(String name) | 创建一个新线程,并指定线程名称。 |
Thread(Runnable target) | 创建一个新线程,并指定Runnable对象。 |
Thread(Runnable target, String name) | 创建一个新线程,指定Runnable对象和名称。 |
Thread类的常用方法: | |
start() | 启动线程,调用run()方法。 |
run() | 线程的执行逻辑,需要重写。 |
getName() | 获取线程名称。 |
setName(String name) | 设置线程名称。 |
getId() | 获取线程ID。 |
isAlive() | 判断线程是否存活。 |
join() | 等待线程执行结束。 |
sleep(long millis) | 让线程休眠指定时间。 |
yield() | 放弃当前线程的CPU时间,让其他线程执行。 |
设置线程优先级: | |
getPriority() | 获取线程优先级。 |
setPriority(int priority) | 设置线程优先级。 |
Thread类的静态常量: | |
MIN_PRIORITY | 最低优先级。 |
NORM_PRIORITY | 正常优先级。 |
MAX_PRIORITY | 最高优先级。 |
守护线程: | |
setDaemon(boolean on) | 将线程设置为守护线程。 |
isDaemon() | 判断线程是否为守护线程。 |
蹩脚翻译
术语 | 英文含义 | 在Java中的含义 |
---|---|---|
Thread | 线程 | 表示一个执行单元,用于并发执行代码。 |
Runnable | 可运行的,可操作的 | 一个接口,表示可执行的任务,通过线程执行。 |
Callable | 可调用的 | 一个接口,类似于Runnable,但可以返回结果或抛出异常。 |
Future | 未来,将来的 | 一个接口,表示异步计算的结果,可用于获取任务的结果。 |