Day -21-多线程

1 程序,进程,线程

程序 : 一组命令的集合,为了完成指定的功能,程序是静态概念,一般保存在硬盘当中

进程 : 正在运行的程序,是一个动态概念,需要保存在内存当中,操作系统会分配对应的PID,当我们直接关闭某个进程的时候,该进行会在运行内存中被销毁

线程 : 一个程序中,不同的执行分支,如果同一个时间节点允许多个线程同时执行的时候,我们称为支持多线程

在Java中,main方法开始执行,就是一个线程,称为主线程

2 并发和并行

并行 : 多个CPU,同时执行多个任务

并发 : 一个CPU,同时执行多个任务

多线程并行 必须CPU要大于等于2 才行

单核CPU是没有多线程的

3多线程优缺点

优点:

提高应用程序的响应。对图形化界面更有意义,可增强用户体验。

提高计算机系统CPU的利用率

改善程序结构。将既长又复杂的进程分为多个线程,独立运行,利于理解和修改

缺点:

程序需要同时执行两个或多个任务。

程序需要实现一些需要等待的任务时,如用户输入、文件读写操作、网络操作、搜索等。

需要一些后台运行的程序时 

4线程创建

public static void main(String[] args){
		test_02();
	}
	public static void test_02(){
		//创建实现类对象
		Processor_01 p = new Processor_01();
		//创建线程类对象
		Thread t1  = new Thread(p);
		//启动线程
		t1.start();
		for(int i =0; i<10;i++){
			System.out.println("main线程" +i);
		}
	}
	public static void test_01(){
		//创建线程类对象
		Thread t1 = new Processor();
		//调用start 方法 启动线程
		t1.start();
		for(int i =0; i<10; i++){
			System.out.println("main线程-->" + i);
		}
	}
}
/**
 * 第一种 创建一个类,继承Thread类,并覆写run方法
 * run方法就是等于是新线程中的main方法
 */
class Processor extends Thread{
@Override
public void run(){
	for(int i= 0; i<10; i++){
		System.out.println("测试线程---" +i);
	}
}
}
/**
 * 第二种,创建一个类,实现Runnable接口,并覆写run方法
 * run方法就是等于是新线程种的main方法
 */
class Processor_01 implements Runnable{
@Override
public void run(){
	for(int i= 0; i<10; i++){
		System.out.println("测试线程11" +i);
	}
}
}

5线程优先级

setPriority() : 设置优先级, java 种有1-10, 10个优先级
 *                     MIN_PRIORITY = 1
 *                     NORM_PRIORITY = 5
 *                     MAX_PRIORITY = 10

6常用方法

	public static void main(String[] args){
			//创建线程对象
			Thread t1 = new Processer();
			//设置名字
			t1.setName("t1");
			//设置优先级为10;
			t1.setPriority(10);
			//设置main 的优先级为1
			Thread.currentThread().setPriority(1);
			//启动线程
			t1.start();
			
			for(int i =0; i<10; i++){
				try{
					//睡眠500秒
					Thread.sleep(500);
				}catch(InterruptedException e){
					e.printStackTrace();
				}
				//获取线程对象并获取线程名字
				System.out.println(Thread.currentThread().getName()+"+++++" +i);
			}
		}
}
class Processer extends Thread{
	@Override
	public void run(){
		for(int i =0; i< 10; i++){
			try{
				Thread.sleep(500);
			}catch(InterruptedException e){
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+ "----" +i);
		}
	}

7 线程停止: 

Stop: 终止某个线程执行,该方法已经过时,不推荐使用,因为有可能导致死锁

一般使用标识符解决

public static void main(String[] args){
			Processer_03 p = new Processer_03();
			Thread t1 = new Thread(p);
			t1.setName("t1");
			t1.start();
			
			try{
				Thread.sleep(7000);
				p.flag = true;
			}catch(InterruptedException e){
				e.printStackTrace();
			}
		}
}
class Processer_03 implements Runnable{
	//加一个标识,标识是否要终止线程
	boolean flag = false;
	@Override
	public void run(){
		for(int i =0;true; i++){
			//判断是否要终止
			if(flag){
				System.out.println(Thread.currentThread().getName()+"线程已经被终止");
				return;
			}
			try{
				Thread.sleep(1000);
				System.out.println(Thread.currentThread().getName()+ "---" +i);
			}catch(InterruptedException e){
				e.printStackTrace();
			}
		}
	}

8线程合并

join: 线程合并    让当前线程等待指定线程执行完  在继续执行

public static void main(String [] args) throws InterruptedException{
		Thread t1 = new Processer_04();
		t1.setName("t1");
		t1.start();
		//到这里。main就要等着t1线程执行完之后在继续执行
		t1.join();
		for(int i =0; i<10;i++){
			try{
				//睡眠300毫秒
				Thread.sleep(300);
			}catch(InterruptedException e){
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"++++" +i);
		}
	}
}
class Processer_04 extends Thread{
	@Override
	public void run(){
		for(int i =0; i<10; i++){
			try{
				//睡眠500毫秒
				Thread.sleep(500);
			}catch(InterruptedException e){
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"----" +i);
		}
	}

9Yield

yield: 静态方法,暂停当前正在执行的线程对象,并执行其他等待中的线程

1 静态方法:意味着跟哪个对象调用没有关系,写在哪个线程中,哪个线程就让位

2给同优先级让位,不同优先级不让位

	public static void main(String[] args){
		//创建线程
		Thread t1 = new Thread(new Processor_05());
		t1.setName("t1");
		//设置t1线程和main线程优先级一致
		t1.setPriority(5);
		Thread.currentThread().setPriority(5);
		t1.start();
		for(int i =0; i<10; i++){
			//让位
			Thread.yield();
			System.out.println(Thread.currentThread().getName()+"====="+i);
		}
	}
}
class Processor_05 implements Runnable{
	@Override
	public void run(){
		for(int i =0; i< 8; i++){
			System.out.println(Thread.currentThread().getName()+"----"+i);
		}

10 线程同步

线程同步: 当多个线程有可能回同时操作同一个数据的时候,为了保证数据一致性,需要进行同步执行
  本质是同步数据,是一种安全机制
 异步编程:线程之间是完全独立的,相互没有影响
 同步编程:线程之间不是完全独立的,相互可能有影响
 同步的场景: 1必须是多线程(必须有并发性,才有可能出错)2多个线程有可能在同以时间操作同一个数据的可能
                  3尤其是同时对数据进行更改操作,查询无所谓

11解决方案

11.1方法锁   使用synchronized

class MyClass_01{
	public synchronized void m1(){
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		System.out.println("加锁的m1方法");
	}
	public synchronized void m2(){
		System.out.println("加锁的m2方法");
	}
	public void m3(){
		System.out.println("未加锁的m3方法");
	}
}

11.2语句块锁

假如 该方法中,只有部分代码需要同步的时候,如果通过synchronized修饰,效率会大大折扣

所以 我们可以通过语句块锁,只锁对应的代码,这样的话该方法中其他的代码还是可以同时执行,效率有所提升

class Processor_08 implements Runnable{
	MyClass_01 mc;
	public Processor_08(MyClass_01 mc) {
		this.mc = mc;
	}
	@Override
	public void run() {
		//获取线程的名字
		String name = Thread.currentThread().getName();
		if(name.equals("t1")){
			mc.m1();
		}else if(name.equals("t2")){
			mc.m2();
		}
		if(name.equals("t3")){
			mc.m3();
		}
	}

12锁

  1. 从JDK 5.0开始,Java提供了更强大的线程同步机制——通过显式定义同

步锁对象来实现同步。同步锁使用Lock对象充当。

  1. java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的 工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象 加锁,线程开始访问共享资源之前应先获得Lock对象。

ReentrantLock 类实现了 Lock ,它拥有与 synchronized 相同的并发性和 内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以 显式加锁、释放锁

class Account1{
	//余额
	private double balance;
	//创建锁对象
	Lock lock = new ReentrantLock();
	public void wihtDraw(double money){
		System.out.println(Thread.currentThread().getName()+"进来了");
		//开始同步
		lock.lock();
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		//语句块锁  
		//余额减去取钱金额
		double after = balance - money;
		//新余额复制给余额
		balance =after;
		System.out.println(Thread.currentThread().getName() + " 取钱成功,取款 : "
				+ money + "元,剩余 : " + balance + " 元 ");
		//解锁
		lock.unlock();
	}

12.1优缺点

 lock 是显示锁,需要手动开启和关闭,synchronized是隐式锁,自动开启,执行完自动关闭
  lock 只有代码块锁,而synchronized 支持方法或代码块锁
  lock锁  需要JVM花费较少的时间来进行资源调度,性能相对较好,而有很好的扩展性
  使用顺序    : Lock锁 ---> 同步代码块锁--->方法锁

13 定时器任务

定时器: 计划任务

只要有一个计划任务,就会开启一个线程,进行计时,到达指定时间后,由该线程来完成这个任务

public class Thread_09_Time {
	public static void main(String[] args){
		// 1 要做的事,也就是任务对象
				// 2 什么时候开始做 , 1000*5 就是5秒之后开始
				// 3 间隔时间,每隔多久做一次 1000*3 每3秒执行一次
				Timer t = new Timer();
				t.schedule(new LogTimerTask(), 1000*5,1000*3);
			}
		
	}
//创建任务
class LogTimerTask extends TimerTask{
	public void run(){
		Date date = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String time = sdf.format(date);
		System.out.println(time);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值