1、使用ProcessBuilder类创建进程,用于打开:D:/数据库/新建文件夹/example.pdf文件。
package com.processes.demo;
import java.io.IOException;
//进程和线程是操作系统中的两个基本概念,它们都是用于执行程序的执行单元,但是有一些关键差异。
//1. 定义:进程是操作系统中资源分配的基本单位,是一个正在执行的程序实例;
//而线程是进程内的一个执行流程,是处理机调度的基本单位。
//2. 资源:进程拥有独立的地址空间、文件描述符、打开的文件等资源,它们可以跨越多个线程共享和传递;
//而线程则共享自己所属进程的资源,包括地址空间、文件描述符等。
//3. 创建和销毁代价:创建和销毁一个进程所需的代价通常比创建和销毁一个线程的代价要大,因为进程需要分配独立的地址空间和系统资源;
//而线程则较为轻量级,创建和销毁的代价相对较小。
//4. 并发性:一个进程可以拥有多个线程,这些线程可以并发执行,共享进程的资源,可以通过信号量、互斥锁等机制实现线程同步与互斥;
//而不同进程之间的并发执行则需要采取进程间通信的方式。
//5. 安全性:由于多个线程共享进程的资源,所有线程可以直接访问进程的中全局变量,容易产生竞态条件等问题,需要使用同步机制进行保护;
//而不同进程之间的资源访问是相互独立的。
//进程是资源分配的基本单位,线程是处理机调度的基本单位。
//进程之间相互独立、线程之间共享资源。
//在多线程编程中,线程之间的通信和同步机制更加简便,但也更容易引发一些问题。
//使用ProcessBuilder类创建进程
//ProcessBuilder的参数应该是一个完整的命令,包括要执行的命令和其参数。
//ProcessBuilder中的路径应该是文件夹的路径,如:D:/数据库/新建文件夹/example.pdf。
public class ProcessOpenPdf {
public static void main(String[] args) {
try {
// 创建ProcessBuilder对象,设置要执行的命令
ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe", "/c", "start", "D:/数据库/新建文件夹/example.pdf");
// 启动进程
Process process = processBuilder.start();
// 等待命令执行完成
int exitCode = process.waitFor();
System.out.println("命令执行完成,退出码为:" + exitCode);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
2、使用Runtime类创建进程,用于打开:D:/数据库/新建文件夹/example.pdf文件。
package com.processes.demo;
import java.io.IOException;
//使用Runtime类创建进程
public class RuntimeOpenPdf {
public static void main(String[] args) {
try {
// 获取运行时对象
Runtime runtime = Runtime.getRuntime();
// 使用默认的关联程序打开 PDF 文件
Process process = runtime.exec("cmd.exe /c start D:/数据库/新建文件夹/example.pdf");
// 等待命令执行完成
int exitCode = process.waitFor();
System.out.println("命令执行完成,退出码为:" + exitCode);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
3、线程:创建一个线程池类,用于创建和管理线程池。
package com.processes.demo;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//创建一个线程池类,用于创建和管理线程池。
//使用Executors.newFixedThreadPool(int)方法创建一个固定大小为3的线程池。
//使用executor.execute(Runnable)方法将任务提交到线程池中执行。
//调用executor.shutdown()方法关闭线程池。
//通过线程池的方式,可以解决频繁创建和销毁线程的开销,并可以有效地控制同时执行的线程数量。
public class ThreadPoolDemo {
public static void main(String[] args) {
// 创建一个固定大小的线程池,大小为3
ExecutorService executor = Executors.newFixedThreadPool(3);
// 创建10个Worker任务,并提交到线程池中执行
for (int i = 1; i <= 10; i++) {
ThreadWorker worker = new ThreadWorker("Worker " + i);
executor.execute(worker);
}
// 关闭线程池
executor.shutdown();
}
}
package com.processes.demo;
//Java线程池是通过Executor框架来实现的。
//创建一个Worker类,用于表示要执行的任务。
public class ThreadWorker implements Runnable {
private String name;
public ThreadWorker(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println("Worker " + name + " is running.");
// 执行具体的任务
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Worker " + name + " finished.");
}
}
运行结果如下:
4、线程调度:
package com.processes.demo;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
//线程调度是通过Java提供的ScheduledExecutorService接口实现的。
//示例代码用于演示如何使用线程调度器定期执行任务。
//使用Executors.newScheduledThreadPool(int)方法创建一个大小为1的线程池调度器。
//然后,使用scheduler.scheduleWithFixedDelay(Runnable, long, long, TimeUnit)方法定期执行任务。
//任务会在程序启动后立即执行一次,然后每隔1秒钟执行一次,执行5秒。
//通过线程调度器的方式,可以方便地执行定期任务,例如:定时清理缓存、定时发送消息等。
//虽然线程可以并发执行,但是在一个系统中通常会有多个线程同时存在,
//并且这些线程可能会竞争共享的资源,比如CPU、内存等。
//为了合理地分配和调度这些资源,保证系统的效率和公平性,需要使用线程调度来控制线程的执行顺序和时间片分配。
//线程调度的主要目的是:
//1. 公平性:通过合理的调度算法,确保各个线程都有机会获得执行的机会,防止某个线程占用资源过长时间,导致其他线程长时间等待。
//2. 性能优化:选择合适的调度策略,最大限度地利用系统资源,提高系统整体的响应速度和吞吐量。
//3. 平衡负载:根据不同线程的优先级、等待时间、资源需求等因素,动态地调整线程的执行顺序和时间片分配,以平衡不同线程之间的负载,提高系统的稳定性和可靠性。
//4. 响应性:及时响应用户的操作,保证用户界面的流畅性和用户体验。
//总之,线程调度是为了协调、平衡和优化系统资源的分配,确保线程能够有序、高效地执行。
public class ScheduleDemo {
public static void main(String[] args) {
// 创建一个大小为1的线程池调度器
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
// 以固定的延迟时间执行任务
scheduler.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
System.out.println("Task executed at " + System.currentTimeMillis());
}
}, 0, 1, TimeUnit.SECONDS);
// 休眠5秒钟,然后关闭线程池调度器
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
scheduler.shutdown();
}
}
运行结果如下:
5、线程安全与线程不安全对比:
package com.processes.demo;
// 创建一个线程不安全的计数器
class CounterUnsafe {
private int count;
public void increment() {
count++;
}
public int getCount() {
return count;
}
}
package com.processes.demo;
import java.util.concurrent.atomic.AtomicInteger;
// 创建一个线程安全的计数器
class CounterSafe {
private AtomicInteger count = new AtomicInteger();
public synchronized void increment() {
count.incrementAndGet();
}
public int getCount() {
return count.get();
}
}
package com.processes.demo;
import java.util.ArrayList;
import java.util.List;
//有两个计数器类:UnsafeCounter和SafeCounter。
//UnsafeCounter是线程不安全的计数器,使用普通的int类型来存储计数值,
//并在increment()方法中直接使用count++对计数值进行自增操作。
//若多个线程同时调用increment()方法,则可能造成竞态条件,导致计数值不准确。
//为了解决线程安全问题,我们使用了SafeCounter类,并使用AtomicInteger来存储计数值。
//AtomicInteger提供了原子操作,保证多线程下的线程安全。
//在main()方法中,创建10个线程,并分别执行1000次计数操作。
//本例未使用线程池,使用List<Thread>来管理线程。
//创建unsafeRunnable和safeRunnable来驱动线程执行计数操作。
//创建并启动线程,并在主线程中等待所有线程执行完成。
//最后输出线程不安全和线程安全的计数结果。
//通过运行上述代码,可以观察到线程不安全的计数结果可能会因为竞态条件而出现错误的计数值,而线程安全的计数结果是准确的。
public class ThreadSafetyDemo {
public static void main(String[] args) throws InterruptedException {
CounterUnsafe unsafeCounter = new CounterUnsafe();
CounterSafe safeCounter = new CounterSafe();
// 创建10个线程,每个线程执行1000次计数操作
int numOfThreads = 10;
int numOfIncrements = 1000;
// 线程不安全示例
Runnable unsafeRunnable = () -> {
for (int i = 0; i < numOfIncrements; i++) {
unsafeCounter.increment();
}
};
// 线程安全示例
Runnable safeRunnable = () -> {
for (int i = 0; i < numOfIncrements; i++) {
safeCounter.increment();
}
};
// 创建并启动线程
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < numOfThreads; i++) {
Thread thread = new Thread(unsafeRunnable);
thread.start();
threads.add(thread);
}
// 等待所有线程执行完成
for (Thread thread : threads) {
thread.join();
}
// 输出线程不安全的计数结果
System.out.println("Unsafe counter: " + unsafeCounter.getCount());
threads.clear();
// 创建并启动线程安全示例
for (int i = 0; i < numOfThreads; i++) {
Thread thread = new Thread(safeRunnable);
thread.start();
threads.add(thread);
}
// 等待所有线程执行完成
for (Thread thread : threads) {
thread.join();
}
// 输出线程安全的计数结果
System.out.println("Safe counter: " + safeCounter.getCount());
}
}
运行结果如下:
6、使用线程池,并发执行安全线程与不安全的线程:
package com.processes.demo;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//使用ExecutorService和Executors工具类创建线程池。
//创建一个固定大小的线程池,其线程数量为10个,即numOfThreads。
//然后,使用线程池执行线程不安全和线程安全的计数操作。
//对于线程不安全的计数器,使用threadPool.execute()方法提交任务,
//每个任务在自己的线程中执行unsafeCounter.increment()操作。
//等待线程池中的所有任务执行完成。
//对于线程安全的计数器,也使用threadPool.execute()方法提交任务,
//每个任务在自己的线程中执行safeCounter.increment()操作。
//同样,等待线程池中的所有任务执行完成。
//最后,输出线程不安全和线程安全的计数结果。
//通过使用线程池,能够更方便地创建和管理线程,实现线程不安全和线程安全的并发操作。
//线程池和线程调度是两个不同的概念。
//线程池是线程的集合,它可以管理和调度多个线程的执行。
//线程池中的线程可以被重复使用,而不需要每次都创建新的线程。
//通过使用线程池,我们可以减少线程的创建和销毁开销,并且可以控制并发执行的线程数量,以避免资源耗尽。
//线程调度是指决定在何时、何种顺序以及如何分配资源给不同的线程或进程。
//线程调度器负责管理操作系统中线程的执行顺序和资源分配。
//线程调度器根据不同的调度策略确定下一个要执行的线程,并将CPU时间片分配给它。
//通过线程调度,可以有效地利用系统资源,提高多线程应用的性能和响应速度。
//线程池是一种用于管理和重复使用线程的机制,而线程调度是一种机制,用于决定在何时以及如何分配CPU时间片给不同的线程。
//线程池可以与线程调度器一起使用,以便更好地管理和调度多线程环境。
public class ThreadSafetyPoolDemo {
public static void main(String[] args) throws InterruptedException {
final int numOfThreads = 10;
final int numOfIncrements = 1000;
final CounterUnsafe unsafeCounter = new CounterUnsafe();
final CounterSafe safeCounter = new CounterSafe();
// 使用线程池创建固定数量的线程
ExecutorService threadPool = Executors.newFixedThreadPool(numOfThreads);
// 线程不安全示例
for (int i = 0; i < numOfThreads; i++) {
threadPool.execute(() -> {
for (int j = 0; j < numOfIncrements; j++) {
unsafeCounter.increment();
}
});
}
// 等待线程池中的所有任务执行完成
threadPool.shutdown();
while (!threadPool.isTerminated()) {
Thread.sleep(1000);
}
// 输出线程不安全的计数结果
System.out.println("Unsafe counter: " + unsafeCounter.getCount());
// 使用线程池创建固定数量的线程安全示例
threadPool = Executors.newFixedThreadPool(numOfThreads);
// 线程安全示例
for (int i = 0; i < numOfThreads; i++) {
threadPool.execute(() -> {
for (int j = 0; j < numOfIncrements; j++) {
safeCounter.increment();
}
});
}
// 等待线程池中的所有任务执行完成
threadPool.shutdown();
while (!threadPool.isTerminated()) {
Thread.sleep(1000);
}
// 输出线程安全的计数结果
System.out.println("Safe counter: " + safeCounter.getCount());
}
}
运行结果如下:
标签:int,创建,调度,线程,进程,执行,public From: https://blog.csdn.net/wehpd/article/details/137437625