目录
一、进程与线程
1、程序:程序是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,可以理解为程序是包含静态代码的文件。例如:浏览器软件、、音乐播放器软件等软件的安装目录和文件。
2、进程:进程是程序的一次执行过程,是系统运行程序的基本单位。例如:正在运行中的浏览器就是一个进程,正在运行中的音乐播放器是另一个进程,同理,正在运行中的QQ和WPS等都是进程。
3、线程:某些进程内部还需要同时执行多个子任务。例如,我们在使用WPS时,WPS可以让我们一边打字,一边进行拼写检查,同时还可以在后台进行自动保存和上传云文档,我们把子任务称为线程。线程是进程划分成的更小的运行单位。
进程和线程的关系就是:一个进程可以包含一个或多个线程,但至少会有一个主线程。
二、线程的创建方式
单线程:单线程就是进程中只有一个线程。单线程在程序执行时,所走的程序路径按照连续顺序排下来,前面的必须处理好,后面的才会执行。
多线程:由一个以上的线程组成的程序称为多线程程序。Java中,一定是从主线程开始执行(main方法),然后在主线程的某个位置创建并启动新的线程。
1、继承Thread类
//主线程
public class thread01 {
public static void main(String[] args) {
//创建线程,调用构造方法为线程命名
subThread t1 = new subThread("线程甲");
subThread t2 = new subThread("线程乙");
subThread t3 = new subThread("线程丙");
//启动线程
t1.start();
t2.start();
t3.start();
}
}
//线程子类
class subThread extends Thread {
public subThread(String name) {
super(name); //调用父类的构造方法
}
//重写run()方法
public void run() {
for (char i = 'A'; i <= 'Z'; i++) {
System.out.println(this.getName() + ":" + i);
}
}
}
2、实现Runnable接口
public class thread02 {
public static void main(String[] args) {
EmailTask eamilTask = new EmailTask();
Thread t1 = new Thread(eamilTask, "线程1");
Thread t2 = new Thread(eamilTask, "线程2");
Thread t3 = new Thread(eamilTask, "线程3");
t1.start();
t2.start();
t3.start();
}
}
//Task抽象类
abstract class Task {
public abstract void execute();
}
//EmailTask类继承Task类并实现Runnable接口
class EmailTask extends Task implements Runnable {
//重写execute()方法
public void execute() {
System.out.println(Thread.currentThread().getName() + "使用JavaMail技术,通过SMTP协议发送了一份电子邮件!");
}
//重写run()方法
public void run() {
execute();
}
}
3、实现Callable接口
//创建3个线程,分别计算1到300的和、301到500的和、501到1000的和,最终获得1到1000的和
public class thread03 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
SumCalcTask task1 = new SumCalcTask(1, 300);
SumCalcTask task2 = new SumCalcTask(301, 500);
SumCalcTask task3 = new SumCalcTask(501, 1000);
//子线程封装为FutureTask对象
FutureTask<Integer> futureTask1 = new FutureTask<Integer>(task1);
FutureTask<Integer> futureTask2 = new FutureTask<Integer>(task2);
FutureTask<Integer> futureTask3 = new FutureTask<Integer>(task3);
Thread t1 = new Thread(futureTask1);
Thread t2 = new Thread(futureTask2);
Thread t3 = new Thread(futureTask3);
// 线程启动-->futureTask1.run()-->callable.call()-->set()-->outcome-->futureTask1
t1.start();
t2.start();
t3.start();
System.out.println("开始分别获取:");
Integer sum1 = futureTask1.get();
Integer sum2 = futureTask2.get();
Integer sum3 = futureTask3.get();
System.out.println("输出计算结果:");
System.out.println(sum1 + sum2 + sum3);
}
}
class SumCalcTask implements Callable<Integer> {
private int begin, end;
public SumCalcTask(int begin, int end) {
this.begin = begin;
this.end = end;
}
public Integer call() throws Exception {
int sum = 0;
for (int i = begin; i <= end; i++) {
sum = sum + i;
}
System.out.println(Thread.currentThread().getName() + ":" + "sum=" + sum);
return sum;
}
}
4、创建线程池
public class thread04 {
public static void main(String[] args) {
// 固定数量的线程池
ExecutorService executorService = Executors.newFixedThreadPool(7);
// 不固定数量的线程请求
while (true) {
executorService.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName() + "进行了一次投票!");
try {
Thread.sleep(1000); //当前线程休眠1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
}
案例:创建一个StringBuffer对象,使用不同的创建线程方式,将 "ABCDE"、"abcde"、"12345"、"@#$%&"拼接。
public class thread05 {
public static void main(String[] args) throws InterruptedException {
StringBuffer sb = new StringBuffer();
//创建线程
//方式一:继承Tread类
Thread t1 = new Thread() {
public void run() {
for (char c = 'A'; c <= 'E'; c++) {
sb.append(c);
}
};
};
//方式二:实现Runnable接口
Thread t2 = new Thread(new Runnable() {
public void run() {
for (char c = 'a'; c <= 'e'; c++) {
sb.append(c);
}
}
});
//方式三:实现Callable接口
Thread t3 = new Thread(new FutureTask<String>(new Callable<String>() {
@Override
public String call() throws Exception {
for (char c = '1'; c <= '5'; c++) {
sb.append(c);
}
return sb.toString();
}
}));
//方式四:创建线程池
ExecutorService threadPool = Executors.newFixedThreadPool(1);
threadPool.execute(new Runnable() {
public void run() {
char[] arr = { '@', '#', '$', '%', '&' };
for (int i = 0; i < arr.length; i++) {
sb.append(arr[i]);
}
}
});
threadPool.shutdown();
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
System.out.println(sb);
}
}