第七章 多线程
1.掌握进程和线程的概念和区别
1.1.进程
开启多个软件同时运行
1.2.线程
在同一个软件中做不同的事情
2.多线程
2.1.什么是多线程
- 如果在一一个进程中同时运行了多个线程,用来完成不同的工作,则称之为多线程
-
多个线程交替舌用CPU资源,而非真正的并行执行 多个线程交替舌用cpu资源,而非真正的并行执行
2.2.多线程的好处
- 充分利用CPU的资源
-
简化编程模型
-
带来良好的用户体验
3.主线程
3.1.Thread类
-
Java提供了java.lang.Thread类支持多线程编程
3.2.主线程
- main()方法即为主线程入口
- 产生其他子线程的线程
- 必须最后完成执行,因为它执行各种关闭动作
尽管主线程在程序启动时自动创建,但它可以由一个Thread 对象控制。为此,需要调用方法
currentThread()获得它的一个引用,currentThread()方 法是Thread类的公有的静态成员。它的通常形式如下?
static Thread currentThread ();
1 /** 2 * 获取和设置主线程的名字 3 */ 4 public class Texst { 5 public static void main(String[] args) { 6 //1.获取主线程对象. 7 Thread t=Thread.currentThread(); 8 System.out.println("当前线程的名字是:"+t.getName());//获取线程名字 9 t.setName("MyjavaThread ");//更改线程名字 10 System.out.println("改后线程的名字是:"+t.getName()); 11 } 12 }
获取当前线程的名字 :Thread.currentThread().getName()
4继承Thread类创建线程
- 定义MyThread类继承Thread类
-
重写run()方法,编写线程执行体
-
创建线程对象,调用start()方法启动线程
- 要重写run(),不重写也不会报错
1 /** 2 * 1.创建MyThread类,继承Thread类的方式创建线程 3 * 2.重写Thread类里的run()方法 4 */ 5 public class MyThread extends Thread{ 6 public void run(){//重写run()方法 7 for (int i=0;i<10;i++){ 8 System.out.println("当前线程名字"+Thread.currentThread().getName()+":"+i); 9 } 10 } 11 }
获得当前线程的名字:Thread.currentThread().getName()
1 /** 2 * 输出类 3 */ 4 public class TexsThread { 5 public static void main(String[] args) {
6 //1.调用MyThread 7 MyThread my1=new MyThread(); 8 MyThread my2=new MyThread(); 9 //2.启动线程 10 //my1.start();//交替执行 11 //my2.start(); 12 my1.run(); 13 my2.run();//1.只有主线程一条执行路径 2.一次调用两次run()方法 14 } 15 }
运行结果
4.1.常见的问题
5.实现Runnable接口创建类
-
定义MyRunnable类实现Runnable接口
-
实现run0方法,编写线程执行体
-
创建线程对象,调用start()方法启动线程
- 必须要重写run()方法
-
1 /** 2 * 实现Runnable接口方式创建线程 3 */ 4 public class MyRunnable implements Runnable { 5 @Override 6 public void run() { 7 for (int i=0;i<10;i++){ 8 System.out.println(Thread.currentThread().getName()+" :"+i); 9 } 10 } 11 }
1 /** 2 * 输出类 3 */ 4 public class TexsRunnanle { 5 public static void main(String[] args) { 6 //1.创建线程对象 7 Runnable my=new MyRunnable(); 8 //2.创建线程 Thread 线程名字=new Thread(线程对象名); 9 Thread th=new Thread(my,"MyThread");//这可以修改线程名字 10 //3. 启动线程 11 th.start(); 12 } 13 }
6.比较两种创建线程的方式
推荐使用实现Runnable接口方式创建线程
总结:
线程的状态和调度
1.线程的状态
2.线程的调度
- 线程调度指按照特定机制为多个线程分配CPU的使用权
2.1.线程的优先级
- 线程优先级由1~10表示,1最低,默认优先级为5,线程优先级由1~10表示,1最低,默认优先级为5
-
优先级高的线程获得CPU资源的概率较大
1 /** 2 * 1.创建MyThread类,继承Thread类的方式创建线程 3 * 2.重写Thread类里的run()方法 4 */ 5 public class MyThread extends Thread{ 6 public void run(){//重写run()方法 7 for (int i=0;i<10;i++){ 8 System.out.println("当前线程名字"+Thread.currentThread().getName()+":"+i); 9 } 10 } 11 }
1 /** 2 * 设置线程优先级 3 */ 4 public class Texst { 5 public static void main(String[] args) { 6 Thread th1=new Thread(new MyThread(),"线程A");
//设置线程的名字 7 Thread th2=new Thread(new MyThread(),"线程B"); 8 th1.setPriority(Thread.MIN_PRIORITY);//设置线程优先级 9 th2.setPriority(Thread.MAX_PRIORITY); 10 th1.start();//启动线程 11 th2.start(); 12 } 13
设置现成的优先级:
2.2.线程休眠
-
让线程暂时睡眠指定时长,线程进入阻塞状态 让线程暂时睡眠指定时长,线程进入阻塞状态
- 睡眠时间过后线程会再进入可运行状态 睡眠时间过后线程会再进入可运行状态
public static void sleep(long millis)
- millis为休眠时长, 以毫秒为单位
- 调用sleep(方法需处理InterruptedException异常
1 /** 2 * 创建一个休眠方法 3 */ 4 public class Wait { 5 //创建一个bySec静态方法 6 public static void bySec(long time){//静态方法 7 for (int i=0;i<time;i++){ 8 System.out.println(i+1+"秒"); 9 try { 10 Thread.sleep(1000);//设置休眠时间 11 } catch (InterruptedException e) { 12 e.printStackTrace(); 13 } 14 } 15 } 16 }
1 /** 2 * 测试类 3 */ 4 public class Texst { 5 public static void main(String[] args) { 6 System.out.println("------------线程开始---------------"); 7 Wait.bySec(5);//让主线程休眠5秒 8 System.out.println("------------线程结束---------------"); 9 } 10 }
2.3.线程的强制运行
- 使当前线程暂停执行,等待其他线程结束后再继续执行本线程
- millis:以毫秒为单位的等待时长
-
nanos:要等待的附加纳秒时长
-
需处理InterruptedException异常
1 /** 2 * 子线程 3 */ 4 public class MyRunnable implements Runnable{ 5 @Override 6 public void run() { 7 for (int i=0;i<10;i++){ 8 try { 9 Thread.sleep(100);//设置休眠,便于交叉执行 10 } catch (InterruptedException e) { 11 e.printStackTrace(); 12 } 13 System.out.println(Thread.currentThread().getName()+":"+i); 14 } 15 } 16 }
1 public class Texst { 2 public static void main(String[] args) { 3 Thread thread=new Thread(new MyRunnable(),"Ther"); 4 thread.start(); 5 for (int i=0;i<20;i++){ 6 if (i==5){ 7 try { 8 thread.join();//再停主线程,让子线程先执行 9 }catch (InterruptedException e){ 10 e.printStackTrace(); 11 } 12 } 13 try { 14 Thread.sleep(100);//线程休眠 15 } catch (InterruptedException e) { 16 e.printStackTrace(); 17 } 18 System.out.println(Thread.currentThread().getName()+":"+i); 19 } } 20 }
2.4.线程的礼让
- 暂停当前线程,允许其他具有相同优先级的线程获得运行机会
-
该线程处于就绪状态,不转为阻塞状态
- public static void yield()
-
只是提供一种可能,但是不能保证一定会实现礼让
1 public class MyThread implements Runnable{ 2 @Override 3 public void run() { 4 for (int i=0;i<5;i++){ 5 System.out.println(Thread.currentThread().getName()+" :"+i); 6 if (i==3){//当i==3时,线程礼让,当前线程将cpu资源让出, 7 8 System.out.print("线程礼让:"); 9 Thread.yield(); 10 } 11 try { 12 Thread.sleep(100); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 } 17 } 18 }
1 /** 2 * 测试类 3 */ 4 public class Texts { 5 public static void main(String[] args) { 6 Thread thread1=new Thread(new MyThread(),"线程A"); 7 Thread thread2=new Thread(new MyThread(),"线程B"); 8 thread1.start(); 9 thread2.start(); 10 } 11 }
3.总结
3.1.线程的五个状态
-
创建、就绪、阻塞、运行、死亡
3.2 .线程调度的方法