JAVA线程概述

1、线程名称
  • 以下代码输出Thread-0、Thread-1,因为虽然线程没开启,但在对象创建的时候就已经定义好名称了

    package bear.utils;
    
    public class MainTest {
    
    	public static void main(String[] args) {
    		
    		Deom d1 = new Deom();
    		Deom d2 = new Deom();
    		
    		d1.run();
    		d2.run();
    	}
    }
    
    class Deom extends Thread{
    	
    	@Override
    	public void run() {
    		System.out.println(getName());
    	}
    }
    
  • 拿到当前运行线程对象,获取当前运行线程的名称,以下代码输出结果为:main

    public class MainTest {
    
    	public static void main(String[] args) {
    		
    		Deom d1 = new Deom();
    		d1.run();
    		
    		// 改为d1.start();的话则输出Thread-0
    	}
    }
    
    class Deom extends Thread{
    	
    	@Override
    	public void run() {
    		System.out.println(Thread.currentThread().getName());
    	}
    }
    
  • 指定线程名称

    public class MainTest {
    
    	public static void main(String[] args) {
    		
    		Deom d1 = new Deom("hehe");
    		d1.start();
    	}
    }
    
    class Deom extends Thread{
    	
    	Deom(String name){
    		super(name);
    	}
    	
    	@Override
    	public void run() {
    		System.out.println(Thread.currentThread().getName());
    	}
    }
    
2、线程的生命周期


3、实现Runnable接口
  • 好处

    • 1,将线程的任务从线程的子类中分离出来,进行了单独的封装。按照面向对象的思想将任务的封装成对象。

    • 2,避免了java单继承的局限性。

    • 所以,这种方式创建线程较为常用。

  • 原理

    class Thread {
    
    	private Runnable r;
    
    	Thread() {
    
    	}
    
    	Thread(Runnable r) {
    		this.r = r;
    	}
    
    	public void run() {
    	
    		if (r != null){
    		    r.run();
    		}
    	}
    
    	public void start() {
    		run();
    	}
    }
    
4、wait和sleep的区别
  • wait可以指定时间也可以不指定。sleep必须指定时间。

  • 在同步中时,对cpu的执行权和锁的处理不同。

    • wait:释放执行权,释放锁。
    • sleep:释放执行权,不释放锁。
  • 同步代码块中具备执行资格的可以有多个,但具备执行权的只能有一个

    class Demo {
    
    	void show() throws InterruptedException {
    		synchronized (this) {
    			// t0 t1 t2(此时t0 t1 t2都挂在这里了,当t3执行notifyAll的时候,这三者就都具备了执行权)
    			wait();
    
    			// t3释放锁的时候,t0 t1 t2只能有一个线程能拿到锁,如t0拿到了锁,则在t0释放锁之前,t1t2依然运行不了
    		}
    	}
    
    	void method() {
    		synchronized (this) {
    			notifyAll();// t3
    		}
    	}
    }
    
5、停止线程
  • 1,stop方法(已过时)

  • 2,run方法结束(怎么控制线程的任务结束呢?任务中都会有循环结构,只要控制住循环就可以结束任务。控制循环通常就用定义标记来完成。)

    • 但是如果线程处于了冻结状态,无法读取标记。如何结束呢?

    • 可以使用interrupt()方法将线程从冻结状态强制恢复到运行状态中来,让线程具备cpu的执行资格(中断睡眠状态)。

    • 但是强制动作会发生InterruptedException,记得要处理。

      public static void main(String[] args) throws InterruptedException {
      
      	Thread t = new Thread() {
      		
      		private boolean flag = true;
      		
      		public void run() {
      			while (flag) {
      				try {
      					System.out.println("hehe");
      					Thread.sleep(5000000); // wait()
      					System.out.println("sleep over");
      				} catch (InterruptedException e) {
      					flag = false;
      				}
      			}
      			System.out.println("exit");
      		};
      	};
      
      	t.start();
      
      	Thread.sleep(200);
      	
      	// 执行中断之后,sleep over不会输出
      	t.interrupt();
      }
      
    • 当线程没有处于冻结状态时,也可以使用以下方法终止线程

      public static void main(String[] args) throws InterruptedException {
      
      	Thread t = new Thread() {
      		public void run() {
      			// 当主线程执行t.interrupt()的时候,interrupted()会返回ture
      			while (!interrupted())
      				System.out.println("hehe");
      			
      			// 再次调用interrupted()时,会返回false
      			System.out.println(interrupted());
      		};
      	};
      	
      	t.start();
      	
      	Thread.sleep(200);
      	t.interrupt();
      }
      
6、守护线程
  • 支持性线程,如垃圾回收线程,随程序的结束而结束。

  • 如果虚拟机中剩下的所有线程都是守护线程的话,在所有线程会自动结束。

  • 通过以下代码来指定线程为守护线程

    • setDaemon方法必须在start方法之前执行

    • 如果setDaemon方法在start之后执行,那么会抛IllegalThreadStateException异常,同时线程依然为前台线程

      /**
       * 守护线程方法演示
       * 
       * @author huangxj 2018216 
       * 
       * @version v1.0
       */
      public class MainTest {
      
          public static void main(String[] args) {
          
              Thread t = new Thread(new Runnable() {
              
              	@Override
              	public void run() {
              		while (true) {
              			try {
              				System.out.println("线程运行中。。。。");
              				Thread.sleep(1000);
              			} catch (InterruptedException e) {
              				e.printStackTrace();
              			}
              		}
              	}
              });
          
              // t线程会随主线程的结束而结束
              t.setDaemon(true);
              t.start();
          }
      }
      
      
7、线程的join方法
  • 在线程a中执行了线程b的join方法,那么线程a就会释放执行权和执行资格,让b线程先执行,等待b线程执行完毕后,a线程才会重新得到执行资格

    /**
     * join方法演示
     * 
     * @author huangxj 2018216 
     * 
     * @version v1.0
     */
    public class MainTest {
    
    	public static void main(String[] args) throws InterruptedException {
    
    		Thread t0 = new Thread(new Runnable() {
    
    			@Override
    			public void run() {
    				for (int x = 0; x < 50; x++) {
    					System.out.println(Thread.currentThread().getName() + "....." + x);
    				}
    			}
    		});
    
    		t0.start();
    
    		System.out.println("主线程执行中,准备让t0线程先执行!");
    
    		// 执行了这一句之后,主线程会释放执行权和执行资格,等待t0线程执行完毕之后才重新获得执行资格
    		t0.join();
    
    		System.out.println("t0线程执行完毕!");
    
    		// 继续执行主线程的任务
    		for (int x = 0; x < 50; x++) {
    			System.out.println(Thread.currentThread().getName() + "....." + x);
    		}
    	}
    }
    
8、线程的优先级
  • 通过t0.setPriority来设置线程的优先级,优先级越高或cpu执行权的几率越高(1到10)

    Thread t0 = new Thread();
    t0.start();
    t0.setPriority(Thread.MAX_PRIORITY);
    
9、线程组
  • 创建线程时可以指定线程所属的线程组。

  • 通过线程组可以对一堆线程执行批量操作。

    public class MainTest {
    
        public static void main(String[] args) throws InterruptedException {
        
        	Runnable run = new Runnable() {
        
        		@Override
        		public void run() {
        			while(true)
        				System.out.println(Thread.currentThread());
        		}
        	};
        	
        	ThreadGroup threadGroup0 = new ThreadGroup("threadGroup0");
        
        	Thread t0 = new Thread(threadGroup0, run);
        	Thread t1 = new Thread(threadGroup0, run);
        	
        	t0.start();
        	t1.start();
        	
        	Thread.sleep(1000);
        	threadGroup0.stop();
        }
    }
    
10、释放线程当前执行线程的执行权
  • 通过调用Thread.yield()方法来实现

  • 调用了该方法,当前线程会释放执行权,cpu将会执行其他线程

11、线程注意事项
  • 以下代码输出:Thread run...

    Runnable run = new Runnable() {
    
    	@Override
    	public void run() {
    		System.out.println("Runnable run...");
    	}
    };
    
    new Thread(run) {
    	@Override
    	public void run() {
    		System.out.println("Thread run...");
    	}
    }.start();
    
  • 以下代码有没有问题?如果有问题的话错误发生在哪一行?

    • 发生在第一行,因为未实现抽象方法run(),要么类应该被abstract修饰

      class Test implements Runnable{
      	public void run(Thread t){}
      }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值