线程

线程 Thread

一、定义

进程中的一个执行控制单元,执行路径

线程分类:

  • 单线程:安全性高,但是效率低
  • 多线程:安全性低,但是效率高
  • 二、创建线程的几种方式

    1. 继承Thread类,重写run()方法
      • run()定义线程体
      • start() 开启线程
    2. 实现Runnable接口,重写run()方法 ---推荐
    3. 实现Callable接口,重写call()方法:了解

    2.1、继承Thread类

    步骤实例:

    //继承Thread类
    public class ThreadDemo01 extends Thread{
    	//定义线程体
    	@Override
    	public void run() {
    		for(int i=1;i<=100;i++){
    			System.out.println("一边吃饭.....");
    		}
    	}
    	
    	public static void main(String[] args) {
    		//创建线程对象:创建Thread子类的对象
    		ThreadDemo01 th=new ThreadDemo01();
    		//开启线程 :准备好了,cpu可以调度了
    		th.start();  
            //th.run(); //方法的调用,单线程,run()执行完毕以后才会继续执行main方法中的代码
            //默认主线程
    		for(int i=1;i<=100;i++){
    			System.out.println("一边说话.....");
    		}
    	}
    }
    
    2.2、实现Runnable接口类

    步骤实例:

    //实现Runnable接口
    public class ThreadDemo02 implements Runnable{
    	//重写run方法
    	@Override
    	public void run() {
    		for(int i=1;i<=20;i++){
                //捕捉异常
    			try {
    				Thread.sleep(100);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			System.out.println("一边学习.....");
    		}
    	}
    	
    	public static void main(String[] args) {
    		//利用静态代理
    		ThreadDemo02 th=new ThreadDemo02();
    		Thread t=new Thread(th);
            //开启线程
    		t.start();
    		
    		for(int i=1;i<=20;i++){
    			try {
    				Thread.sleep(100);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			System.out.println("一边陪女朋友.....");
    		}
    	}
    
    }
    

    优点:

  • 避免单继承的局限性
  • 实现资源共享
  • 2.3、匿名内部类实现方式
    public class Test01 {
    	public static void main(String[] args) {
    		new Thread(new Runnable() {
    			
    			@Override
    			public void run() {
    				for(int i=0;i<10;i++){
    					System.out.println(Thread.currentThread().getName()+"我是匿名内部类");
    				}
    				try {
    					Thread.sleep(200);
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		}).start();
    	}
    }
    
    2.4、Lambda实现方式
    new Thread(()->{
    				for(int i=0;i<20;i++){
    					try {
    						Thread.sleep(2);
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    					System.out.println("一遍嘿嘿笑...");
    				}
    			}).start();
    
    2.5、内部类实现方式
    public class Demo02 {
    	static class Inner implements Runnable{
    		//静态内部类
    		@Override
    		public void run() {
    			for(int i=0;i<20;i++){
    				try {
    					Thread.sleep(2);
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    				System.out.println("一遍讲课...");
    			}
    		}
    		
    	}
    	public static void main(String[] args) {
    		new Thread(new Inner()).start();
    	}
    }
    
    2.6、火车购票实例
    public class Web12306_03 implements Runnable{
    	int tickets=100;  //100张票
    
    	/*
    	 * 买票的流程功能
    	 */
    	@Override
    	public void run() {
    		while(true){
    			//结束买票的条件
    			if(tickets<=0){
    				break;
    			}
    			try {
    				Thread.sleep(200);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    			//static Thread currentThread();返回当前线程对象
    			System.out.println(Thread.currentThread().getName()+"正在买第"+tickets--);
    		}
    	}
    	
    	public static void main(String[] args) {
    		Web12306_03 web=new Web12306_03();  //100
    		//创建线程  资源共享
    		Thread th1=new Thread(web,"张三");
    		Thread th2=new Thread(web,"李四");
    		Thread th3=new Thread(web,"王五");
            //开启线程
    		th1.start();
    		th2.start();
    		th3.start();
    	}
    	
    }
    

    注:当多个线程同时操作同一份资源的时候,可能会出现线程不安全问题

    三、线程的状态

    有5种状态:

    • 新生: new Thread()
    • 就绪: start(),就绪状态的线程会进入到就绪队列中,等待cpu调度
    • 运行: 当cpu非配时间片给线程,这个线程就会进入运行状态开始运行
    • 阻塞: sleep()...
    • 终止: 线程结束

    注:

    1. 如果一个线程进入阻塞状态,阻塞状态解除也无法直接进入运行状态,会进入就绪状态
    2. 如果一个线程已经死亡,无法恢复就算重新开启线程也不是原来的那一个

    3.1

    1)如何进入终止状态
    • 正常执行完毕
    • 添加外部表示判断
    2)如何进入就绪状态
    • start()
    • 阻塞状态解除
    • yield()
    • 线程切换
    3)如何进入阻塞状态
    • sleep()
    • wait()
    • join()
    • IO 操作

    sleep(ms) 线程睡眠.. (抱着资源睡觉)

  • 模拟网络延迟
  • 放大发生问题的可能性
  • 3.2、yield()方法

    会让出cpu的资源,让线程直接进入就绪状态

    public class YieldDemo02 {
    	
    	static class Inner implements Runnable{
    
    		@Override
    		public void run() {
    			System.out.println(Thread.currentThread().getName()+"开始执行");
    			Thread.yield();
    			System.out.println(Thread.currentThread().getName()+"结束执行");
    		}
    		
    	}
    	
    	public static void main(String[] args) {
    		Inner in=new Inner();
    		new Thread(in,"A" ).start();
    		new Thread(in,"B" ).start();
    	}
    	
    	
    }
    

    3.3、join()方法

    也叫插队方法,使被插队的线程进入阻塞状态

    3.4、获取线程状态的方法

    getState() 返回线程的枚举类型状态值

    线程的优先级:  1~10  1最小  10最大   默认5

  • int getPriority()  返回线程的优先级
  • void setPriority(int newPriority)  更改线程的优先级
  • public class StateDemo04 {
    	public static void main(String[] args) {
    		Thread th=new Thread(()->{
    			for(int i=1;i<=10;i++){
    				if(i==5){
    					try {
    						Thread.sleep(2000);
    					} catch (Exception e) {
    						e.printStackTrace();
    					}
    				}
    			}
    		});
    		System.out.println(th.getState());  
    		th.start();
    		System.out.println(th.getPriority());
    		Thread th2=new Thread(()->{System.out.println("哈哈哈2");});
    		Thread th3=new Thread(()->{System.out.println("哈哈哈3");});
    		System.out.println(th2.getPriority());
    		System.out.println(th3.getPriority());
    		th2.setPriority(1);
    		th3.setPriority(6);
    		th2.start();
    		th3.start();
    	}
    }
    

    四、线程安全

    当多线程,同时操作同一份资源的时候有可能存在线程不安全问题

    如何控制线程安全:

  • 锁-->同步锁 synchronized
  • 1)、同步方法

    使用关键字synchronized修饰的方法,一旦被一个线程访问,则整个方法全部被锁住,其他线程则无法访问。

    public void run() {
    		while(true){
    			payTicket();
    		}
    		
    	}
    
    public  synchronized void payTicket() {
    	if(tickets>0){	
             try{
                 Thread.sleep(200);
             }catch(InterruptedException e){
                 e.printStackTrace();
             }
             System.out.println(Thread.currentThread().getName()+"正在买"+tickets--);
    	}
    }
    

  • 静态方法
  • public static synchronized void payTicket() {
    	if(tickets>0){	
             try{
                 Thread.sleep(200);
             }catch(InterruptedException e){
                 e.printStackTrace();
             }
             System.out.println(Thread.currentThread().getName()+"正在				买"+tickets--);
    	}
    }
    
    2)、同步块

    格式: synchronized(引用类型|对象|类)

    public void run() {
    		while(true){
    			//结束买票的条件
                //锁类
    			synchronized (Web12306_02.class) {
    				if(tickets<=0){
    					break;
    				}
    				try {
    					Thread.sleep(200);
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    				System.out.println(Thread.currentThread().getName()+"正在买第"+tickets--);
    			}
    		}
    	}
    

    注:

  • 锁要锁不变的内容,才能锁住
  • 锁的范围太大,效率低,锁的范围太小,锁不住
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值