当程序需要同时执行两个或多个任务就引出多线程概念,一份工一个人干和几个人干,谁快一目了然。
线程和进程区别
进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多 个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创 建、运行到消亡的过程。
线程:进程内部的一个独立执行单元;一个进程可以同时并发的运行多个线程,可以理解为一个进程便相当 于一个单 CPU 操作系统,而线程便是这个系统中运行的多个任务。
进程和线程的关系就是:一个进程可以包含一个或多个线程,但至少会有一个线程。
并发与并行
并行:指两个或多个事件在同一时刻发生(同时发生)。
并发:指两个或多个事件在同一个时间段内发生。
多线程的优点
- 提高应用程序的响应。堆图像化界面更有意义,可以增强用户体验。
- 提高计算机系CPU的利用率。
- 改善程序结构。将既长又复杂的进程分为多个线程,独立运行,利于理解和修改。
多线程的三种写法:
第一种继承Thread类:
- 创建一个继承于Thread类的子类。
- 重写Thread类的run()方法。
- 创建Thread类的子类的对象。
- 通过此对象调用start()来启动一个线程。
代码如下所示:
package Thread;
public class Threadd extends Thread{
@Override
public void run() {
System.out.println("这是多线程");
}
public static void main(String[] args) {
Threadd td=new Threadd() ;
td.start();
Threadd td1=new Threadd() ;
td1.start();
Threadd td2=new Threadd() ;
td2.start();
}
}
执行结果:
第二种实现Runnable接口:
- 创建一个实现Runnable接口的类。
- 实现类去实现Runnable接口中的抽象方法:run()。
- 创建实现类的对象。
- 将此对象作为参数传到Thread类的构造器中,创建Thread类的对象。
- 通过Thread类的对象调用start()方法。
代码如下所示:
package Thread;
public class Impl implements Runnable{
@Override
public void run() {
System.out.println("这是Runnable的多线程");
}
public static void main(String[] args) {
Impl i=new Impl() ;
Thread td=new Thread(i);
td.start();
Impl i1=new Impl() ;
Thread td1=new Thread(i1);
td1.start();
Impl i2=new Impl() ;
Thread td2=new Thread(i2);
td2.start();
}
}
执行结果:
第三种是实现Callable接口:
- 相比run()方法,可以有返回值
- 方法可以抛出异常
- 支持泛型的返回值
代码如下:
package Thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Call implements Callable<Integer> {
static int i;
@Override
public Integer call() throws Exception {
for (;i<20;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
}
return i;
}
public static void main(String[] args) {
Call call=new Call();
FutureTask<Integer> ft=new FutureTask<>(call);
for (int i=0;i<20;i++){
System.out.println("当前执行到......"+i);
}System.exit(0);
try {
Integer result= ft.get();
System.out.println(result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
执行结果:
一直到19停止。
小练习:三个窗口同时卖票 用实现Runnable方式
public class Test1 implements Runnable {
static int i=1;
static int count=100;
static Object obj=new Object();
@Override
public void run() {
for (; i<100;i++) {
try {
Thread.sleep(2000);
synchronized (obj) {
if (count > 0) {
System.out.println("你在"+Thread.currentThread().getName()+"购买第" + i + "张票");
count--;
} else {
System.out.println("票已售空");
break;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Test1 t1=new Test1();
Thread td=new Thread(t1);
td.setName("窗口一");
td.start();
Test1 te=new Test1();
Thread td1=new Thread(te);
td1.setName("窗口二");
td1.start();
Test1 ts=new Test1();
Thread td2=new Thread(ts);
td2.setName("窗口三");
td2.start();
}
}
执行结果:
依次类推到100停止售票。