多线程的知识点

多线程

  1. 一个进程包含多个线程
  2. 程序是一个静态的概念,当程序运行起来,cpu分配内存和资源,即进程。
  3. 多个线程由调度器(cpu)安排调度,所以其先后顺序是不能干预

线程的创建

  1. 继承Thread

    /**
     * 测试线程安全
     * 原子性
     * 可见性
     * 有序性
     * @author 
     *
     */
    public class Test03 {
    	
    	private static int count;
    	
    	private static class Thread1 extends Thread{
    		@Override
    		public void run() {
    			for(int i=0;i<=1000;i++){
    				count++;
    				try {
    					Thread.sleep(1);
    				} catch (Exception e) {
    					// TODO: handle exception
    				}
    			}
    		}
    	}
    
    	public static void main(String[] args) throws InterruptedException {
    		Thread1 thread1=new Thread1();
    		Thread1 thread2=new Thread1();
    		thread1.start();
    		thread2.start();
    		thread1.join();
    		thread2.join();
    		System.out.println(count);
    
    	}
    
    }
    
    
  2. 实现接口Runnable

    public class Test04 implements Runnable {
    	private static int count1;
    	public Test04 (int i){
    		count1=i;
    		System.out.println("线程"+i+"启动");
    	}
    	@Override
    	public void run() {
    		for(int i=1;i<3;i++){
    			System.out.println("执行线程"+i);
    		}
    		try {
    			Thread.sleep((int)Math.random()*1000);
    		} catch (Exception e) {
    		}
    		
    	}
    	public static void main(String[] args) {
    		Thread t1=new Thread(new Test04(1));
    		t1.start();
    		Thread t2=new Thread(new Test04(2));
    		t2.start();
    
    	}
    
    }
    
    
  3. 实现接口Callable

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;


/**
 * 实现callable接口
 * @author 
 *
 */
public class Test06 implements Callable<Boolean>{
	
	@Override
	public Boolean call() throws Exception {
		for(int i=1;i<=20;i++){
			System.out.println("执行线程"+i);
		}
		return true;
	}

	public static void main(String[] args) throws InterruptedException, ExecutionException {
		Test06 t1=new Test06();
		Test06 t2=new Test06();
		Test06 t3=new Test06();
		
		//创建执行服务
		ExecutorService ser=Executors.newFixedThreadPool(3);
		//提交执行
		Future<Boolean> r1=ser.submit(t1);
		Future<Boolean> r2=ser.submit(t2);
		Future<Boolean> r3=ser.submit(t3);
		
		//获取结果
		boolean rs1=r1.get();
		boolean rs2=r2.get();
		boolean rs3=r3.get();
		
		//关闭服务
		ser.shutdownNow();
		

	}

}

静态代理模式

  1. 总结

    • 真实对象和代理对象都要实现同一个接口
    • 代理对象要代理真实角色,即传递一个真实对象给代理对象
  2. 好处

    • 代理对象可以做很多真实对象做不了的事情,做真实对象之外的事情

    • 真实对象专注做自己的事情

    /**
     * 静态代理 staticProxy
     * @author 
     *
     */
    public class Test07 {
    
    	public static void main(String[] args) {
    		WeddingCompany weddingCompany=new WeddingCompany(new You());
    		weddingCompany.mappyMarry();
    	}
    
    }
    
    interface Marry{
    	void mappyMarry();
    }
    
    class You implements Marry{
    
    	@Override
    	public void mappyMarry() {
    		System.out.println("结婚了,好开心");
    	}
    	
    }
    
    class WeddingCompany implements Marry{
    	private You target;
    	
    	public WeddingCompany(You target) {
    		this.target=target;
    	}
    	
    	@Override
    	public void mappyMarry() {
    		before();
    		target.mappyMarry();
    		after();
    	}
    	void before(){
    		System.out.println("结婚前,布置场地");
    	}
    	void after(){
    		System.out.println("结婚后,收尾款");
    	}
    }
    
    
    

Lamda表达式

作用:

  1. 避免匿名内部类定义过多
  2. 属于函数式编程

函数式接口定义:

  1. 任何接口,如果只包含一个抽象方法,则称为函数式接口
  2. 使用lambda表达式简化

总结:

  • lambda表达式只有一行代码的情况下,如果有多行,那么就用代码块包裹
  • 前提是接口为函数式接口
  • 多个参数也可以去掉参数类型,要去掉就都去掉,必须加上括号
/**
 * lambda表达式:jdk1.8之后
 * @author 
 *
 */
public class Test08 {
	//2.定义一个静态内部类
	static class Like2 implements ILike{

		@Override
		public void love(int a, int b) {
			System.out.println("i love you->"+a);
			System.out.println("i love you->"+b);
		}
		
	}

	public static void main(String[] args) {
		//3.定义一个内部类
		class Like3 implements ILike{

			@Override
			public void love(int a, int b) {
				System.out.println("i love you->"+a);
				System.out.println("i love you->"+b);
			}
			
		}
		
		ILike like=new Like();
		like.love(1, 2);
		
		ILike like2=new Like2();
		like2.love(3, 4);
		
		ILike like3=new Like3();
		like3.love(5, 6);
		
		//4.定义一个匿名内部类
		ILike like4=new ILike() {
			@Override
			public void love(int a, int b) {
				System.out.println("i love you->"+a);
				System.out.println("i love you->"+b);
			}
		};
		like4.love(7, 8);
		
		//使用lambda表达式
		ILike like5=(a,b)->System.out.println("i love you->"+a);
		like5.love(9, 10);
	
	}

}

//定义一个函数式接口:只有一个抽象方法
interface ILike{
	void love(int a,int b);
}

//1.定义一个类实现接口
class Like implements ILike{

	@Override
	public void love(int a, int b) {
		System.out.println("i love you->"+a);
		System.out.println("i love you->"+b);
	}
	
}

线程状态

五大状态

  • 创建状态
  • 就绪状态
  • 阻塞状态
  • 运行状态
  • 死亡状态

停止线程

  • 不推荐使用stop()和destory()方法
  • 推荐线程自己停下来
  • 使用标志位停止线程
/**
 * 线程停止
 * 1、建议使用标志位停止线程
 * 2、不推荐使用jdk的stop和destory方法
 * 3、使线程自动停止下来更加安全
 * @author 
 *
 */
public class Test09 implements Runnable {
	private static boolean flag=true;
	public static void main(String[] args) {
		new Thread(new Test09()).start();
		for (int i = 0; i < 1000; i++) {
			if(i==900){
				flag=false;
				System.out.println("停止线程");
			}
			System.out.println("主线程----"+i);
		}
			
	}

	@Override
	public void run() {
		int i=1;
		while(flag){
			System.out.println("运行线程----"+i++);
		}
	}

}

线程休眠

Thread.sleep();

线程休眠案例:

import java.text.SimpleDateFormat;
import java.util.Date;


/**
 * 线程休眠
 * 1、模拟延时
 * 2、倒计时
 * 3、获取当前时间
 * @author 
 *
 */
public class Test10 {

	public static void main(String[] args) {
//		tendDown();
		Date starTime=new Date(System.currentTimeMillis());
		while(true){
			try {
				Thread.sleep(1000);
				System.out.println(new SimpleDateFormat("HH:mm:ss").format(starTime));
				starTime=new Date(System.currentTimeMillis());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public static void tendDown(){
		int num=10;
		while(true){
			try {
				Thread.sleep(1000);
				System.out.println(num--);
				if(num<=0){
					break;
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

线程礼让

  • 礼让线程,让当前正在执行的线程暂停,但不阻塞
  • 让运行状态转变为就绪状态
  • 礼让不一定成功,看cpu心情:让正在运行的线程重新与就绪进程竞争
/**
 * 
 * @author 线程礼让YieId
 *
 */
public class Test11 {

	public static void main(String[] args) {
		new Thread(new YieId(),"a").start();
		new Thread(new YieId(),"b").start();

	}
	

}

class YieId implements Runnable{

	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName()+"开始执行");
		Thread.yield();
		System.out.println(Thread.currentThread().getName()+"结束执行");
		
	}
	
}

线程强制执行

Join:可理解为插队,优先执行插入线程,执行完成后再执行主线程

/**
 * 线程强制执行join
 * @author 
 *
 */
public class Test12 implements Runnable {
	
	public static void main(String[] args) throws InterruptedException {
		Thread thread1=new Thread(new Test12());
		thread1.start();
		for (int i = 0; i <1000; i++) {	
			if(i==500){
				thread1.join();
			}
			System.out.println("main执行"+i);
		}

	}

	@Override
	public void run() {
		for (int i = 0; i < 1000; i++) {
			System.out.println("线程执行--"+i);
		}	
	}

}

观察线程状态

使用Thread.State state=t1.getState();—>获取当前进程的状态

/**
 * 
 * @author 线程状态的观测:State
 *
 */
public class Test13{

	public static void main(String[] args) {
		Thread t1= new Thread(()->{
			for (int i = 0; i < 5; i++) {
				try {
					Thread.sleep(1000);
					
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}	
			}
			
			System.out.println("线程执行结束");
		});
		
		Thread.State state=t1.getState();
		System.out.println(state);
		
		t1.start();
		state=t1.getState();
		System.out.println(state);
		
		//监测线程状态
		while(state!=Thread.State.TERMINATED){
			try {
				Thread.sleep(200);//每隔200ms监测一次
				state=t1.getState();
				System.out.println(state);	
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

}

线程的优先级

  1. 使用getPriority .setPriority(int xxx)改变线程优先级(1-10)
public class Test14 {

	public static void main(String[] args) {
		
		System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());

		MyPriority p1=new MyPriority();
		MyPriority p2=new MyPriority();
		MyPriority p3=new MyPriority();
		
		Thread t1= new Thread(p1,"p1");
		Thread t2= new Thread(p2,"p2");
		Thread t3= new Thread(p3,"p3");
		
		t1.setPriority(10);
		t1.start();
		
		t2.setPriority(1);
		t2.start();
		
		t3.start();
		
		

	}

}

class MyPriority implements Runnable{

	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
	}
	
}

  1. 获取当前线程的名称Thread.currentThread.getName();
  2. 获取当前线程的优先级Thread.currentThread.getPriority();
  3. 设置线程优先级应该在线程启动之前
  4. 主线程的优先级不可改变
  5. 默认优先级为5

守护线程

daemon

  • 线程分为用户线程和后台线程
  • 虚拟机必须保护用户线程执行完毕
  • 虚拟机不用等待守护线程执行完毕
  • 如后台记录操作日志、垃圾回收线程(gc线程)

线程同步

并发:多个线程操作同一个资源

  • 线程同步是一种等待机制

  • 队列和锁

  • 锁机制:synchronized:当一个线程获得对象的排它锁,独占资源,其他线程必须等待

  • 弊端:

    1. 一个线程持有锁对导致其他需要此锁的线程挂起
    2. 会降低性能
    3. 如果一个优先级高的线程等待一个优先级低的线程释放锁,会导致优先级倒置,引起性能问题

线程同步安全

  1. 不安全的买票

    public class Test15 {
    
    	public static void main(String[] args) {
    		BuyTicket station=new BuyTicket();
    		
    		new Thread(station,"小明").start();
    		new Thread(station,"小红").start();
    		new Thread(station,"小黄").start();
    		
    		
    	}
    
    }
    
    class BuyTicket implements Runnable{
    	
    	private int tickets=10;
    	private boolean flag=true;
    
    	@Override
    	public void run() {
    		while(flag){
    			buy();	
    		}
    	}
    	
        public void buy(){
        	if(tickets<=0){
        		flag=false;	
        		return;
        	}
        	try {
    			Thread.sleep(1000);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
        	System.out.println(Thread.currentThread().getName()+"买到了"+tickets--);
        }
    	
    }
    
    
  2. 不安全银行取钱

    public class Test16 {
    
    	public static void main(String[] args) {
    		Account account=new Account("基金", 100);
    		
    		Drawing you=new Drawing(account, 50, "xxx");
    		Drawing she=new Drawing(account, 100, "yyy");
    		
    		you.start();
    		she.start();
    	}
    
    }
    //创建一个账户
    class Account{
    	public String name;
    	public int money;
    	public Account(String name,int money){
    		this.name=name;
    		this.money=money;
    	}
    }
    
    class Drawing extends Thread{
    	
    	private Account account;
    	
    	private int drawingMoney;
    	
    	private int nowMoney;
    	
    	public Drawing(Account account,int drawingMoney,String name) {
    		super(name);
    		this.account=account;
    		this.drawingMoney=drawingMoney;
    	}
    	
    	@Override
    	public void run() {
    		if(account.money-drawingMoney<0){
    			System.out.println("账号余额不足");
    			return;
    		}
    		
    		try {
    			Thread.sleep(1000);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		account.money=account.money-drawingMoney;
    		
    		nowMoney=nowMoney+drawingMoney;
    		
    		System.out.println(account.name+"的钱:"+account.money);
    		
    		System.out.println(this.getName()+"手里的钱:"+nowMoney);
    		
    	}
    }
    
    
  3. 不安全的线程集合

    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 线程不安全的集合
     * @author 
     *
     */
    public class Test17 {
    
    	public static void main(String[] args) {
    		List<String> threadList=new ArrayList<String>();
    		for (int i = 0; i < 10000; i++) {
    			new Thread(()->{
    				threadList.add(Thread.currentThread().getName());
    			}).start();
    		}
    	
    		System.out.println(threadList.size());
    
    	}
    
    }
    
    

同步方法

  1. public synchronized void xxx(){};
  2. synchronized默认锁的是this

同步块

  1. synchronized (Obj){}
  2. Obj称之为同步监视器
  3. JUC:CopyOnWriteArrayList list =new CopyOnWriteArrayList();本身就是线程安全的

死锁

条件

  1. 互斥条件
  2. 请求与保持条件
  3. 不剥夺条件
  4. 循环等待

Lock锁

  • 同步锁使用Lock对象

  • 接口Lock,其实现类ReentrantLock

  • Lock是显式锁,需要手动开启和关闭锁

  • Lock只能对代码块加锁,synchronized即可代码块和方法

线程协作

wait()等待,会释放锁

notify()唤醒

线程池

//创建线程池
ExecutorService service=Executors.newFixdThreadPool(线程池大小);

//对于Runable接口,使用execute执行,没有返回类型,只执行
//new MyThread()指实现Runnable接口的类,不需要使用静态代理
service.execute(new MyThread());

//对于callable接口,使用submit执行,使用Futrue接收
Futrue<返回类型> result=service.submit();
//获取返回值
类型 r1=result.get();

//关闭线程池
service.shutDownNow();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值