线程学习笔记

线程学习笔记

  • 进程:是系统进行资源分配和调度的独立单元,每一个进程都有它的独立内存空间和系统资源。

  • 线程:是进程里面的一条执行路径,每个线程共享进程里面的内存空间和系统资源。同一进程中的线程是互抢资源的竞争关系。

  • 线程与进程:一个进程中可以有一个到多个线程,一个线程只属于一个进程。CPU时间片:内存空间和系统资源。

  • 线程实现的三种方式。前两种是重点

    • 继承thread类方式实现线程
      如:
    /**
     * 自定义线程类
     * @author 
     * @version 1.0 2019年9月9日
     */
    public class MyThread extends Thread{
    	/**
    	 * 设置线程名字
    	 * @param s
    	 */
    	public MyThread(String s) {
    		this.setName(s);
    	}
    	/**
    	 * 重写run方法
    	 */
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		
    		for (int i = 0; i < 10; i++) {
    				System.out.println(Thread.currentThread().getName()+":"+i);		
    		}
    
    	}
    }
    
    /**
     * 测试类
     * @author 
     * @version 1.0 2019年9月9日
     */
    public class Test {
    	public static void main(String[] args) {
    		// 创建线程对象
    		MyThread t1 = new MyThread("线程1");
    		MyThread t2 = new MyThread("线程2");
    		// 调用方法给线程设置名称
    		// t1.setName("线程A");
    		// t2.setName("线程B");
    
    		// 启动线程
    		t1.start();
    		t2.start();
    	}
    
    }
    
    
    
    • 实现Runnable接口方式实现线程,如:
    /**
       * 线程任务类
       * @author sx
       * @version 1.0 2019年9月9日
       */
      public class MyRunnable implements Runnable{
      
      	/**
      	 * 重写父接口中任务方法
      	 */
      	@Override
      	public void run() {
      		for (int i = 1; i <=10; i++) {
      			System.out.println(Thread.currentThread().getName()+":"+i);
      		}
      		
      	}
      }
      
      public static void main(String[] args) {
      		//创建任务对象
      		MyRunnable r1=new MyRunnable();
      		MyRunnable r2=new MyRunnable();
      		//将任务对象封装成线程对象
      		Thread t1=new Thread(r1, "线程1");
      		Thread t2=new Thread(r2, "线程2");
      		//启动线程
      		t1.start();
      		t2.start();
      }
      //测试类一样
    
    
    • 实现Callable接口方式实现线程(少用)
  • 给线程取名常用方式:

    • 调用setName方法
    • 使用构造方法
  • 继承Thread类方法 VS 实现Runnable接口方式实现

    • 代码简洁:继承Thread类实现线程代码更加简洁,实现Runnable接口方式代码稍微复杂一点。
    • 可扩展性:继承Thread类不能再继承其他类,只能实现接口,所以扩展性更差;实现Runnable接口方式实现线程还可以在继承其他的类,实现其他的接口,所以扩展性更好。
    • 资源共享性:继承Thread类方式,只能通过静态变量来实现资源共享,但是耗内存,实现Runnable接口方式,只要让多个线程共用一个任务对象就可以实现资源共享,所以不耗内存。
  • 线程的优先级:优先级越高的线程抢占资源的概率越高,优先级低的线程抢占资源的概率越低。优先级高的线程不一定抢得到cpu时间片,优先级低的线程也不一定抢不到cpu时间片。设置线程优先级实现方式:要在启动线程之前设置线程的优先级:线程对象.setPriority(int newPriority):

    MyThread t1=new MyThread();
   	MyThread t2=new MyThread();
   	//设置线程的优先级
   	t1.setPriority(Thread.MAX_PRIORITY);
   	t2.setPriority(Thread.MIN_PRIORITY);
   	//启动子线程
   	t1.start();
   	t2.start();

  • 线程休眠:在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),一旦休眠期到了,又重新参加资源抢占。设置线程睡眠:对象名.sleep(long millis)或者 Thread.sleep(long millis)(推荐后者):
public static void main(String[] args) throws InterruptedException {
   	//声明一个数组存6个学员的姓名
   	String[] names= {"aa","bb","cc","ddd","ee","ff"};
   	//生成随机数,作为抽取学员姓名的索引
   	int r=(int)(Math.random()*names.length);
   	for (int i = 3; i >=1; i--) {
   		System.out.println(i);
   		Thread.sleep(1000);
   	}
   	System.out.println("抽中的学员为:"+names[r]);
   }

  • 线程礼让:暂停当前正在执行的线程对象,并执行其他线程。使用对象名.yield();或者Thread.yield();实际上当一个线程礼让,另外一个线程还是有可能抢占不到资源,有点类似于线程的优先级,没有什么太大的效果。
/**
* 线程任务类
* @author sx
* @version 1.0 2019年9月9日
*/
   public class MyRunnable implements Runnable{
   
   	/**
   	 * 重写父接口中任务方法
   	 */
   	@Override
   	public void run() {
   		for (int i = 1; i <=100; i++) {
   			System.out.println(Thread.currentThread().getName()+":"+i);
   			//线程B每运行一次就礼让 一次
   			if (Thread.currentThread().getName().equals("线程B")) {
   				Thread.yield();
   			}
   		}		
   	}
   }
   
   public static void main(String[] args) {
   		//创建任务对象
   		MyRunnable r1=new MyRunnable();
   		MyRunnable r2=new MyRunnable();
   		//将任务对象封装成线程对象
   		Thread t1=new Thread(r1, "线程A");
   		Thread t2=new Thread(r2, "线程B");
   		//启动线程
   		t1.start();
   		t2.start();
   	}

  • 线程合并将一个线程合并到另一个线程中,全成一条执行路线,合并过来的线程先执行完,再执行原来的线程。线程合并的使用:线程对象.join();
    • 子线程合并到主线程中:
    public static void main(String[] args) throws InterruptedException {
     	//创建子线程对象
     	MyThread1 t1=new MyThread1();
     	
     	//启动线程
     	t1.start();
     	
     	//主线程执行任务
     	for (int i = 1; i <=200; i++) {
     		System.out.println(Thread.currentThread().getName()+":"+i);
     		//当主线程运行到10时, 子线程插队
     		if (i==10) {
     			t1.join();
     		}
     	}
     }
    
    
    • 子线程A合并到子线程B中:
    /**
      * 线程类
      * @author 
      * @version 1.0 2019年9月9日
      */
     public class MyThread2 extends Thread{
     //声明一个线程对象
     MyThread2 t;
     
     public MyThread2() {
     	
     }
     
     /**
      * 将线程对象作为参数传过来构造方法
      * @param t
      */
     public MyThread2(MyThread2 t) {
     	this.t=t;
     }
    
     /**
      * 重写父类的任务方法
      */
     @Override
     public void run() {
     	for (int i = 1; i <=200; i++) {
     		System.out.println(Thread.currentThread().getName()+":"+i);
     		//当线程B运行到10时,线程A合并过来
     		if (i==10&&Thread.currentThread().getName().equals("线程B")) 			{
     			try {
     				t.join();
     			} catch (InterruptedException e) {
     				// TODO Auto-generated catch block
     				e.printStackTrace();
     			}
     		}
     	}
     }
     }
     		
     			public static void main(String[] args) throws InterruptedException {
     	//创建子线程对象
     	MyThread2 t1=new MyThread2();
     	//用构造方法将线程A对象传线程B对象作属性
     	MyThread2 t2=new MyThread2(t1);
     	//设置线程的名称
     	t1.setName("线程A");
     	t2.setName("线程B");
     	//启动线程
     	t1.start();
     	t2.start();
     }
    
    
  • 线程中断:
    • 用中断方法来中断线程:
        //interrupt()中断线程。
    	//interrupted() 测试当前线程是否已经中断
    	
    	/**
     * 线程类
     * @author 
     * @version 1.0 2019年9月9日
     */
    public class MyThread1 extends Thread{
    
    	/**
    	 * 重写父类的任务方法
    	 */
    	@Override
    	public void run() {
    		for (int i = 1; i <=200; i++) {
    			//判断中断状态值,跳出循环结构
    			if (Thread.currentThread().isInterrupted()==true) {
    				break;
    			}
    			System.out.println(Thread.currentThread().getName()+":"+i);
    		}
    	}
        } 
    
    		public static void main(String[] args) throws InterruptedException {
    		//创建线程对象
    		MyThread1 t1=new MyThread1();
    		//启动线程
    		t1.start();
    		
    		for (int i = 1; i <=200; i++) {
    			System.out.println(Thread.currentThread().getName()+":"+i);
    			//当主线程运行10时,中断子线程
    			if (i==10) {
    				t1.interrupt();//改变子线程的中断状态值
    				//主线程睡眠让出cpu时间片让子线程中断
    				Thread.sleep(2000);
    			}
    		}
    	}
    
    
    • 作标记方法:
    public class MyThread2 extends Thread{
     //声明一个成员变量作标记
     boolean flag=false;
    
     /**
      * 重写父类的任务方法
      */
     @Override
     public void run() {
     	for (int i = 1; i <=200; i++) {
     		//判断中断状态值,跳出循环结构
     		if (flag==true) {
     			break;
     		}
     		System.out.println(Thread.currentThread().getName()+":"+i);
     	    }
     	}
     }
    
     		public static void main(String[] args) throws InterruptedException {
     	//创建线程对象
     	MyThread2 t1=new MyThread2();
     	//启动线程
     	t1.start();
     	
     	for (int i = 1; i <=200; i++) {
     		System.out.println(Thread.currentThread().getName()+":"+i);
     		//当主线程运行10时,中断子线程
     		if (i==10) {
     			t1.flag=true;//改变子线程的中断状态值
     			//主线程睡眠让出cpu时间片让子线程中断
     			Thread.sleep(2000);
     		}
     	}
     }
    
    
  • 线程的生命周期
    1. 新建状态:当一个线程对象被New出来后,它就处于新建状态.
    2. 就绪状态:当一个线程调用start()方法后或者阻塞状态的线程解除阻塞时,它就处于就绪状态.
    3. 运行状态:当一个就绪状态的线程抢到cpu时间片时,运行run()时间时,它就处于运行状态.
    4. 阻塞状态:当一个线程调用sleep(时间)或wait()时,它就处于阻塞状态.
    5. 死亡状态:当一个线程调用stop()方法时或run()方法执行结束后,线程即处于死亡状态。处于 死亡状态的线程不具有继续运行的能力。
  • 守护线程(精灵线程):守护线程守护的是所有非守护线程,一旦所有非守护线程死亡,守护线程自动死亡.在线程启动之前设置线程是否为守护线程:线程对象.setDaemon(boolean on)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值