首页 > 系统相关 >进程与线程

进程与线程

时间:2024-04-06 21:00:30浏览次数:25  
标签:int 创建 调度 线程 进程 执行 public

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

相关文章

  • 常用API(一):StringBuilder (用StringBuilder操作字符串效率更高比String) StringBuff
     packagecom.itheima.StringBuilder1;publicclassStringBuilder1{publicstaticvoidmain(String[]args){StringBuilders=newStringBuilder();StringBuilders1=newStringBuilder("pengsuoqun");//创建新字符串s1.append(1......
  • 创建线程的方式
    创建线程的方式1.ClassThreadpackagecom.lisus2000.style;publicclassTest01extendsThread{@Overridepublicvoidrun(){System.out.println("继承Thread类,重写run方法实现线程.");}publicstaticvoidmain(String[]args)throw......
  • 线程等待通知机制
    join()是等待线程结束。wait是等待线程通知,并不一定是执行结束。能更加精细的控制线程执行的顺序。在什么情况下使用线程等待通知呢?“线程饿死问题”,一个线程频繁的获取锁和释放锁,由于获取锁的速度太快,其他的线程抢不到,那么就会影响到代码的执行速度。而等待通知机制就......
  • 理解进程和线程
    一.进程和线程进程和线程的存在目的都是为了实现并发执行,提高系统的资源利用率和响应速度。进程概念:​ 自己话理解,进程就是,一个程序,当操作系统执行时,让他成为了一个动起来的实体,此时这个活动的实体就是进程。进程是程序执行时的一个实例。每个进程都有自己的地址空间、内......
  • 并发编程(二):线程安全检查工具
    对于验证代码是否是线程安全,往往是十分困难的,有一些工具可以帮我们简化这项任务,以尽可能保证并发的正确性。ThreadSanitizer谷歌出品,内置于编译器的一种线程安全分析工具,使用方法就是在编译时加上-fsanitize=thread配置项即可。现在来简单尝试分析如下代码:#include<th......
  • 使用POOL+Queue的多进程爬虫
    前面说的multiprocessing里面的Process动态生成多个进程,如果限制数量过大就繁琐了,现在就可以使用Pool进程的功效。在使用Pool前,我们先了解一下阻塞和非阻塞两个概念。阻塞和非阻塞关注的是程序在等待调用结果时的状态。阻塞要等到回调结果出来,在有结果之前,当前进程会被挂起。......
  • 多线程(33)ConcurrentHashMap
    ConcurrentHashMap是Java并发包中提供的一个线程安全的哈希表实现。与传统的同步容器相比,ConcurrentHashMap通过一种分段锁的机制实现了更高的并发度。本节将深入探讨其设计原理,结合源码进行分析,并通过代码示例来演示其使用方法。设计原理ConcurrentHashMap的设计理......
  • 多线程(34)CopyOnWriteArrayList
    CopyOnWriteArrayList是Java中一个线程安全的ArrayList变体,属于java.util.concurrent包。它通过在所有修改操作(如add,set等)上执行显式复制来实现线程安全。这种设计适用于列表读操作的数量远远大于写操作的场景。设计原理CopyOnWriteArrayList的基本思想是,每当......
  • K8s 守护进程之 DaemonSet:深入解析
    ......
  • 操作系统综合题之“给进程数和资源数,判断是否安全状态和列出安全序列”
    一、问题:若有3个进程共享9个资源,且当前资源分配情况如下进程已占资源数最大需求数P126P236P315 请回答以及下问题1.目前系统是否处于安全状态?2.如果是,给出进程执行的安全序列,如果不是,请说明理由 二、参考答案1.目前处于安全状态2.安全序列为:P......