进程和线程的区别
进程是正在运行的程序,windows任务管理器中列出的每一行便是一个进程。进程是系统进行资源分配和调用的独立单位,每一个进程都有它自己的内存空间和系统资源。
一个进程可以包含多个线程。比如Java运行在运行时,除了主线程之外,还会至少有一个gc线程用来负责垃圾回收。
进程的切换相对来讲是比较耗时的,每次切换都要加载、保存上下文。但是线程之间的切换负担就比较轻。因此Java中一般都会使用多线程来执行并行任务。
进程和线程的创建
进程创建:
- 通过Runtime.exec()方法来创建一个进程
- 通过ProcessBuilder的start方法来创建进程
线程创建:
1、继承Thread类,重写其run()方法。则该类的实例化对象的start()方法被调用时即创建了新的线程。
package com.tong.leetcode.thread;
public class ThreadTest {
static class MyThread extends Thread {
@Override
public void run() {
// 随便做一些事情。这里打印了10次线程的名字
for (int i = 0; i < 10; i++) {
System.out.println(getName() + " " + i);
}
}
}
public static void main(String[] args) {
// 创建了10个线程,每次创建打印当前线程的名字
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " --> " + i);
new MyThread().start();
}
}
}
运行结果太长这里就不贴了。能明显看到不同线程的执行存在切换。
2、实现Runnable接口。重写其Run()方法。则该类的实例化对象的start()方法被调用时即创建了新的线程。
package com.tong.leetcode.thread;
public class RunnableTest implements Runnable {
@Override
public void run() {
// 随便做一些事情。这里打印了10次线程的名字
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
public static void main(String[] args) {
// 创建了10个线程,每次创建打印当前线程的名字
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " --> " + i);
new ThreadTest.MyThread().start();
}
}
}
3、使用Callable和FutureTask配合。创建Callable的实现类,实现其call()方法。然后使用FutureTask包装Callable。使用其start()方法启动新线程,使用其get()方法获取子线程的返回值。注意get()方法会等待对应线程执行完毕后才会执行,因此会阻塞其他线程。
package com.tong.leetcode.thread;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class CallableTest implements Callable<String> {
@Override
public String call() {
// 随便做一些事情。这里打印了10次线程的名字
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
return "the end " + Thread.currentThread().getName();
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
List<FutureTask<String>> futureTaskList = new Vector<>();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " --> " + i);
CallableTest callableTest = new CallableTest();
FutureTask<String> futureTask = new FutureTask<>(callableTest);
new Thread(futureTask).start();
futureTaskList.add(futureTask);
}
for (FutureTask<String> stringFutureTask : futureTaskList) {
System.out.println("运行结果:" + stringFutureTask.get());
}
}
}
4、使用Callable+Future+线程池。这种方法类似第三种,使用线程池可以对线程管控得更加精准。
package com.tong.leetcode.thread;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.*;
public class CallableThreadPollTest implements Callable<String> {
@Override
public String call() {
// 随便做一些事情。这里打印了10次线程的名字
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
return "the end " + Thread.currentThread().getName();
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
List<Future<String>> futureList = new Vector<>(10);
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " --> " + i);
CallableThreadPollTest callableTest = new CallableThreadPollTest();
Future<String> future = executorService.submit(callableTest);
futureList.add(future);
}
for (Future<String> future : futureList) {
System.out.println("运行结果:" + future.get());
}
}
}
参考链接:
Java 进程线程理解www.jianshu.com