目录
一、什么是多线程?
进程:程序的基本执行实体(一个正在运行的软件)
线程:应用软件中互相独立,可以同时运行的功能。这些功能比较多就成了多线程。
二、多线程的作用
利用等待时间,让CPU在多个程序中进行切换,提高效率。
三、并发与并行
并发:在同一时刻,有多个指令在单个CPU上交替执行
并行:在同一时刻,有多个指令在多个CPU上同时执行
四、多线程的实现
1、继承Thread类的方式
//继承类
public class MyThread extends Thread{
//将类声明为Thread的子类
//重写run方法
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+"Hello World");
}
}
}
//测试类
public class ThreadDome{
public static void main(String[] args){
MyThread t1=new MyThread();
MyThread t2=new MyThread();
t1.setName("线程1");
t2.setName("线程2");
//开启线程
t1.start();
t2.start();
}
}
2、实现Runnable接口的方式
//实现接口类
public class MyRun implements Runnable{
//1、自己定义一个类实现Runnable接口
//2、重写run方法
@Override
public void run() {
for (int i = 0; i < 100; i++) {
//获取到当前进程的对象
//没有继承Thread,所以不能直接使用getName方法
Thread t=Thread.currentThread();
//返回当前线程的对象
System.out.println(t.getName()+"HelloWorld");
/*或者System.out.println(Thread.currentThread().getName()+"HelloWorld");*/
}
}
}
//测试类
public class ThreadDome2 {
public static void main(String[] args){
//3、创建自己的类的对象
MyRun mr=new MyRun();
//4、创建Thread类的对象,并开启线程
Thread t1=new Thread(mr);
Thread t2=new Thread(mr);
t1.setName("线程1");
t2.setName("线程2");
t1.start();
t2.start();
}
}
3、利用Callable接口和Future接口方式
特点:可以获取到多线程运行的结果
//实现类
import java.util.concurrent.Callable;
public class MyCallable implements Callable<Integer> {
//1、创建一个类实现Callable接口
//2、重写call(是有返回值的,表示多线程运行的结果)
@Override
public Integer call() throws Exception {
int sum=0;
for (int i =1; i <= 100; i++) {
sum=sum+i;
}
return sum;
//返回值
}
}
//测试类
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
public class ThreadDome3 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//3、创建自己类的对象(表示多线程要执行的任务)
//4、创建FutureTask的对象(作用管理多线程运行的结果)
//5、创建Thread的对象,并启动
MyCallable mc=new MyCallable();
FutureTask<Integer> ft=new FutureTask<>(mc);
Thread t1=new Thread(ft);
t1.start();
Integer result=ft.get();
System.out.println(result);
}
}
五、实例(利用多线程售票)
1、利用继承Thread的方法
//测试类
public class SaleTicker {
public static void main(String[] args) {
Ticket t1=new Ticket(50);
Ticket t2=new Ticket(50);
t1.setName("窗口1");
t2.setName("窗口2");
t1.start();
t2.start();
}
}
//继承类
public class Ticket extends Thread{
private int num;
public Ticket() {
}
public Ticket(int num) {
this.num = num;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
@Override
public void run() {
while(this.num>0) {
sale();
}
}
public void sale(){
int count=this.num;
count--;
System.out.println(Thread.currentThread().getName()+"正在售出第"+this.num+"张票,剩余"+count+"张票");
this.setNum(count);
}
}
利用lambda表达式改进代码
public class SaleTicker {
public static void main(String[] args) {
Ticket t1=new Ticket(50);
Ticket t2=new Ticket(50);
new Thread(()->{
while(t1.getNum()>0) {
t1.sale();
}
},"窗口1").start();
new Thread(()->{
while(t2.getNum()>0) {
t2.sale();
}
},"窗口2").start();
}
}
2、利用实现接口Runnable的方式
//测试类
public class SaleT {
public static void main(String[] args) {
Ticket1 ticket1=new Ticket1(100);
MyRun mr=new MyRun(ticket1);
new Thread(()->{
while(ticket1.getNum()>0){
mr.run();
}
},"窗口1").start();
new Thread(()->{
while (ticket1.getNum()>0){
mr.run();
}
},"窗口2").start();
}
}
//自定义类
public class Ticket1 {
private int num;
public Ticket1() {
}
public Ticket1(int num) {
this.num = num;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}
//实现Runnable接口的类
public class MyRun implements Runnable{
private Ticket1 ticket1;
public MyRun() {
}
public MyRun(Ticket1 ticket1) {
this.ticket1 = ticket1;
}
public Ticket1 getTicket1() {
return ticket1;
}
public void setTicket1(Ticket1 ticket1) {
this.ticket1 = ticket1;
}
@Override
public void run() {
int num=ticket1.getNum();
System.out.println(Thread.currentThread().getName()+"正在售出第"+num+"张票,剩余"+--num+"张票");
ticket1.setNum(num);
}
}