一、进程:进程是受操作系统管理的基本运行单位;
二、线程:在进程中独立运行的子任务;
三、多线程的好处:
可以在同一时间内运行更多不同种类的任务;
单任务的特点是排队执行,也就是同步,CPU利用率很低;
多任务的特点也就是多线程,同时执行,异步操作,CPU快速切换,提高利用率;
四、Java里面的多线程基础
1、实现多线程的两种方式,继承Thread类,实现Runnable接口,一般最好实现Runnable接口,因为Java是单继承机制,如果继承Thread类,就不能继承其他类,会给程序带来很大的不便;
注意:Thead类是实现了Ruannale接口的,它们是多态关系;
2、非线程安全
主要是指多个线程对同一个对象中的同一个实例变量进行操作时会出现值被更改、值不同步的情况,进而影响程序的执行流程。
3、停止线程
在Java中有以下3种方法可以终止正在运行的线程:
(1)使用退出标志,使线程正常退出,也就是当run方法完成后线程终止;
(2)使用stop方法强行退出,但是已经过时,线程不安全,不建议使用;
(3)使用interrupt方法中断线程;
4、interrpt方法中断线程
调用interrupt方法仅仅是在当前线程中打了一个停止的标记,并不是真的马上停止线程;
(1)Thread.interrupted()方法是一个静态的方法,代表测试当前线程是否已经中断,中断状态返回true,注意当此方法连续执行两次时,第二次会返回false;因为该方法具有将状态标志清除为false的功能;
(2)this.isInterrupted()方法是一个非静态的方法,由线程的对象调用,判断该线程是否已经是中断状态,不具有清除状态的功能,也就是无论调用多少次,返回的结果一样;
1 package concurrent; 2 3 class MyThread1 extends Thread { 4 public void run() { 5 try { 6 for (int i = 0; i < 500000; i++) { 7 if (this.isInterrupted()) { 8 System.out.println("本线程被中断了:马上退出"); 9 throw new InterruptedException(); 10 } 11 System.out.println("i=" + (i + 1)); 12 } 13 System.out.println("for循环外的,线程继续运行,并没有立即被中断!"); 14 } catch (InterruptedException e) { 15 System.out.println("线程被中断后,如果有catch会进入异常处理,之后就不会继续往下运行!"); 16 e.printStackTrace(); 17 } 18 } 19 } 20 public class Testinterrupted { 21 public static void main(String[] args) { 22 try { 23 MyThread1 thread = new MyThread1(); 24 thread.start(); 25 System.out.println(Thread.currentThread().getName()); 26 Thread.sleep(1000);// 把主线程停1秒 27 // thread.interrupt();//中断当前线程操作 28 Thread.currentThread().interrupt();// 中断当前线程操作 29 System.out.println("测试当前线程是否已经停止1:" + Thread.interrupted()); 30 System.out.println("测试当前线程是否已经停止2:" + Thread.interrupted()); 31 thread.interrupt(); 32 System.out.println("测试指定对象线程是否已经停止1:" + thread.isInterrupted()); 33 System.out.println("测试指定对象线程是否已经停止2:" + thread.isInterrupted()); 34 } catch (InterruptedException e) { 35 e.printStackTrace(); 36 } 37 System.out.println("end!"); 38 } 39 }
5、停止线程的方法---异常法
相当于在if判断里面加一个抛出异常,之后在catch里面捕获,利用异常退出线程;
此外还可以直接用return来结束线程,不过还是建议用向上抛出异常来实现线程的停止,使线程停止事件得到传播;
6、stop强制停止线程的不良后果
强制让线程停止可能是一些清理性的工作得不到完成,另外就是对锁定的对象进行了“解锁”,导致数据得不到同步的处理,出现数据不一致的问题。
7、yield方法
Thread.yield()放弃当前的CPU资源的执行权,将它让给其他的任务去占用CPU的执行时间,时间不确定,可能又马上获取到了执行权继续执行;
8、线程的优先级
Java中将线程的优先级分为10个等级,分别是1-10,但是并没有强制对应操作系统中相对应的线程级别,只是大致对应;默认优先级为5,main主线程优先级为5
使用setPriority()设置线程的优先级,getPiority()获取线程的优先级,注意线程的优先级JDK是使用常量来预先设定的,1对于最小,10对应最大;但是并不是越大就越先执行,优先级越高,只是获取CPU切换时间片的几率越大,优先执行的概率较高而已;
1 package concurrent; 2 3 class ThreadA extends Thread { 4 private int count = 0; 5 public int getCount(){ 6 return count; 7 } 8 public void run() { 9 try { 10 for (int i = 0; i < 1000000; i++) { 11 count = i; 12 System.out.println(this.getName()+"-------->"+count); 13 if (count >= 5000) { 14 throw new InterruptedException(); 15 } 16 } 17 } catch (InterruptedException e) { 18 System.out.println(this.getName() + " 线程已经执行完毕!"); 19 } 20 } 21 } 22 23 class ThreadB extends Thread { 24 private int count = 0; 25 public int getCount(){ 26 return count; 27 } 28 public void run() { 29 try { 30 for (int i = 0; i < 1000000; i++) { 31 count = i; 32 System.out.println(this.getName()+"-->"+count); 33 if (count >= 5000) { 34 throw new InterruptedException(); 35 } 36 } 37 } catch (InterruptedException e) { 38 System.out.println(this.getName() + " 线程已经执行完毕!"); 39 } 40 } 41 } 42 43 class MyThread2 extends Thread { 44 45 public void run() { 46 long beginTime = System.currentTimeMillis(); 47 int count = 0; 48 for (int i = 0; i < 10000000; i++) { 49 // Thread.yield(); 50 // 放弃当前的CPU资源的执行权,将它让给其他的任务去占用CPU的执行时间,时间不确定,可能又马上获取到了执行权继续执行; 51 count = count + (i + 1) * 2 / 2; 52 } 53 long endTime = System.currentTimeMillis(); 54 System.out.println(this.getName() + "--" 55 + Thread.currentThread().getPriority()); 56 System.out.println(this.getPriority()); 57 System.out.println(endTime - beginTime); 58 } 59 } 60 61 public class TestYield { 62 public static void main(String[] args) { 63 // MyThread2 m = new MyThread2(); 64 // m.start(); 65 // System.out.println(Thread.currentThread().getName()); 66 // System.out.println(Thread.currentThread().getPriority()); 67 68 try { 69 ThreadA a = new ThreadA(); 70 ThreadB b = new ThreadB(); 71 a.setPriority(Thread.MAX_PRIORITY); 72 b.setPriority(Thread.NORM_PRIORITY - 2); 73 a.start(); 74 b.start(); 75 Thread.sleep(20000); 76 } catch (InterruptedException e) { 77 e.printStackTrace(); 78 } 79 } 80 }
9、守护线程
Java线程中有两种线程,一种是普通的用户线程,另一种是守护线程;
守护线程顾名思义就是守护普通线程的线程,它随着普通线程而生,随普通线程停止后自动销毁,守护线程不能独立存在,典型的守护线程就是JVM的GC线程,作用是为其他线程的运行提供便利服务;
1 package concurrent; 2 3 class ThreadDaemon extends Thread { 4 private int i = 0; 5 public void run() { 6 try { 7 while (true) { 8 i++; 9 System.out.println(this.getName() + "-->" + i); 10 Thread.sleep(1000); 11 /*设置为守护线程后,线程sleep后会自动停止,这样可以当作一种线程停止的手段*/ 12 } 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 } 17 } 18 public class TestDaemon { 19 public static void main(String[] args) { 20 try { 21 ThreadDaemon td = new ThreadDaemon(); 22 td.setDaemon(true); 23 td.start(); 24 Thread.sleep(1000); 25 System.out.println("线程td先设置为守护线程,运行后sleep后即停止了!"); 26 } catch (InterruptedException e) { 27 e.printStackTrace(); 28 } 29 } 30 }