十六、多线程

多线程

同时运行了多个线程,用来完成不同的工作

多个线程交替CPU资源

好处:

充分利用CPU的资源

简化编程模型

带来良好的用户体验

进程和线程的区别

进程

应用程序的执行实例-》进程《-有独立的内存空间和系统资源

线程

CPU调度和分派的基本单位-》线程《-进程中执行运算的最小单位,可完成一个独立的顺序控制流程

主线程

​ java.lang.Tread类支持多线程

​ main()方法即主线程入口
在这里插入图片描述

实现Runnable接口创建线程

  • 自定义Thread类末尾要加Thread
  • 重写run()方法,编写线程执行体
  • 创建线程对象,调用start()方法启动多线程

在main方法里直接调用run()方法只执行一个线程main(单线程),一个执行完在执行一个。

start()方法是多线程交替执行(CPU分配时间片)

继承Thread类

  • 编写简单,可直接操作线程
  • 是用于单根继承

实现Runnable接口

  • 避免单继承局限性
  • 便于共享资源

线程的状态和线程的调度

在这里插入图片描述

线程的五个状态

创建、就绪、阻塞、运行、死亡

线程调度的方法

setPriority(int grade) 优先级调整

// 获得当前线程名
Thread.currentThread().getName();
// 线程优先级最高
setPriority(Thread.MAX_PRIORITY);
// 线程优先级最低
setPriority(Thread.MIN_PRIORITY);

​ sleep(long millis) 线程休眠

Thread.sleep(1000); // 休眠1000毫秒

​ join() 线程强制执行使该线程先执行完毕

​ yield()优先级默认5 由1-10表示让线程暂时书面指定时常,线程进入阻塞状态

public static void main(String[] args) {
		System.out.println("*************线程强制执行*************");
		// 1.创建线程对象
		Thread temp = new Thread(new MyRunnable3(),"temp");
		temp.start();
		for (int i = 0; i < 20; i++) {
			// 当主线程执行到i==5时,暂停主线程,让子线程temp执行完毕之后,主线程再执行
			if (i==5) {
				try {
					temp.join();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
dSystem.out.println(Thread.currentThread().getName()+"运行:"+i);
		}

线程的礼让yield();暂停当前线程,允许其他具有相同优先级的线程获得运行的机会。

该线程处于就绪状态,不转为阻塞状态

该礼让不一定会实现

线程的同步

使用synchronized修饰的方法控制对类成员变量的访问

可以放在访问修饰符前面或后面

synchronized就是为当前线程声明一个锁

使用synchronized关键字修饰的代码块

synchronized (this) {
    while(true) {
        if (count <= 0) {
            break;
        }
        // 1.修改数据(剩余票数、抢到第几张票)
        count--;
        num++;
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // 2.显示信息,反馈用户抢到第几张票
        System.out.println(Thread.currentThread().getName()+"抢到第"+num+"张票,"+"剩余第"+count+"张票");

}

多个并发线程访问同一资源的同步代码块时

  • 同一时刻只能有一个线程进入synchronized(this)同步代码块
  • 当一个线程访问一个synchronized(this)同步代码块时,其他synchronized(this)同步代码块同样被锁定
  • 当一个线程访问一个synchronized(this)同步代码块时,其他线程可以访问非synchronized(this)同步代码
StringBuffer是同步的,StringBuilder非同步
HashTable是同步的,HashMap是非同步的
一般同步的用于多线程,非同步用于单线程

1556770509739

死锁

死锁-两个线程都在等待对方先完成,造成程序的停滞

死锁条件

  • 两个或两个以上的线程在活动

  • 某个线程拿到一个锁以后,还想拿第二个锁,造成所得嵌套

线程池

executors工具类

缓存线程池
public class ThreedPool {
	public static void main(String[] args) {
		ExecutorService es = Executors.newCachedThreadPool();
		
		// 在线程池中执行10个任务
		for (int i = 0; i < 10; i++) {
			es.execute(new MyRunnable(i));
		}
	}
}

class MyRunnable implements Runnable{
	int num;
	public MyRunnable(int num) {
		super();
		this.num = num;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println(Thread.currentThread().getName()+":"+num);
	}
	
}

单线程池
public class ThreedPool {
	public static void main(String[] args) {
		ExecutorService es = Executors.newSingleThreadExecutor();
		
		// 在单线程池中执行任务
		for (int i = 0; i < 10; i++) {
			es.execute(new MyRunnable(i));
		}
	}
}

class MyRunnable implements Runnable{
	int num;
	public MyRunnable(int num) {
		super();
		this.num = num;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println(Thread.currentThread().getName()+":"+num);
	}
	
}

固定线程池
public class ThreedPool2 {
	public static void main(String[] args) {
		ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
		
		// 在线程池中执行3个任务
		for (int i = 0; i < 10; i++) {
			fixedThreadPool.execute(new MyRunnable1(i));
		}
	}
}

class MyRunnable1 implements Runnable{
	int num;
	public MyRunnable1(int num) {
		super();
		this.num = num;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println(Thread.currentThread().getName()+":"+num);
	}
	
}
定时执行任务线程
public class ThreedPool3 {
	public static void main(String[] args) {
		ScheduledExecutorService ses = Executors.newScheduledThreadPool(3);
		System.out.println("**********开始执行************");
		ses.scheduleAtFixedRate(new MyRunnable2(), 5, 2, TimeUnit.SECONDS);
		
	}
}

class MyRunnable2 implements Runnable{
	int num;
	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println(Thread.currentThread().getName()+"延时5s执行,每2s执行一次!");
	}
	
}
自定义线程
ublic class ThreadPool4 {
	public static void main(String[] args) {
		ThreadPoolExecutor tpe = new ThreadPoolExecutor(5,7,300,TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(4));
		for (int i = 1; i <= 12; i++) {
			tpe.execute(new MyRunnable4(i));
			System.out.println("线程池中的线程数:"+tpe.getPoolSize()+"队列中等待执行的线程数:"+tpe.getQueue().size()
					+"已经执行完的线程数:"+tpe.getCompletedTaskCount());
		}
		tpe.shutdown();
	}
}
class MyRunnable4 implements Runnable{
	int num;
	public MyRunnable4(int num) {
		super();
		this.num = num;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println("正在执行任务"+num);
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("任务"+num+"执行完毕!");
	}
}

在这里插入图片描述

序号 名称 类型 含义
1 corePoolSize int 核心线程池大小
2 maximumPoolSize int 最大线程池大小
3 keepAliveTime long 线程最大空闲时间
4 unit TimeUnit 时间单位
5 workQueue BlockingQueue 线程等待队列
6 threadFactory ThreadFactory 线程创建工厂
7 handler RejectedExecutionHandler 拒绝策略

猜你喜欢

转载自blog.csdn.net/Super_Robot/article/details/89469409