多线程

进程(process)

是程序的一次执行过程,或是正在运行的一个程序

线程(thread)

进程可进一步细化为线程,是一个程序内部的一条执行路径

(1)多线程概念

如果在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为"多线程".(多个线程交替占用CPU资源,而非真正的并行执行)
多线程作用:让多部分代码同时执行;

(2)多线程好处

  • 让多部分代码同时执行
  • 带来良好的用户体验
  • 充分利用CPU的资源
  • 简化编程模型

缺点:导致程序运行效率降低。

(3)Thread类

Java提供了java.lang.Thread类支持多线程编程

(4)主线程
  • main()方法即为主线程入口
  • 产生其他子线程的线程
  • 必须最后完成执行,因为它执行各种关闭动作

使用currentThread()方法获取当前线程的对象,是一个静态方法,返回一个Thread对象;

Thread t = Thread.currentThread();
  • 获取主线程名getName();
  • 设置主线程名setName();
public class Demo1 {
	public static void main(String[] args) {
		//1.获取主线程对象
		Thread t = Thread.currentThread();
		System.out.println("当前线程是:"+t.getName());
		t.setName("MyJavaThread");
		System.out.println("当前线程是:"+t.getName());
	}
}



(5)继承Thread类创建线程

  1. 定义类继承Thread类;
  2. 覆盖Thread类中的run方法。
  3. 创建Thread子类对象,即创建了线程对象。
  4. 调用线程对象start方法(启动线程,调用run方法);
//1继承线程类
public class Dog extends Thread {
	private String name;

	public Dog(String name) {
		super();
		this.name = name;
	}

	// 2重写run方法
	@Override
	public void run() {
		for (int i = 1; i <= 20; i++) {
			System.out.println(name + "跑了第" + i + "圈");
		}
	}
}
/** * 继承Thread类创建多线程 * 步骤: * 1.定义类,继承Thread类; * 2.覆盖Thread类中的run方法; * 3.创建Thread子类对象(即线程对象); * 4.调用start方法开启线程,并调用线程的run方法执行; * @Hudie */
public class ThreadDemo2 {
	public static void main(String[] args) {
		//3创建Thread子类对象
		Dog d1 = new Dog("花花");
		Dog d2 = new Dog("小黄");
		//4调用start方法
		d1.start();
		d2.start();
// d1.run();
// d2.run();
	}
}

执行结果:

多个线程交替执行,不是真正的"并行";
线程每次执行时长由分配的CPU时间片长度决定;

启动多线程直接调用run()方法会怎样?
①:调用run()方法整个线程只有一条执行路径:


②:调用start()方法就是开启了多个子线程,多个子线程和主线程并行交替执行.


(6)实现Runnable接口创建线程

  1. 定义一个类实现Runnable接口;
  2. 覆盖接口中的run方法;
  3. 通过Thread类建立线程对象,并将Runnable接口的子类对象作为Thread类的构造函数的参数传递进来;
  4. 调用Thread类的start方法开启线程;
//①定义一个类实现Runnable接口; 
public class Cat implements Runnable {
	private String name;

	public Cat(String name) {
		super();
		this.name = name;
	}

	// ②覆盖接口中的run方法
	@Override
	public void run() {
		for (int i = 1; i <= 20; i++) {
			System.out.println(name + "跑了第" + i + "圈");
		}
	}
}
public class ThreeadDemo3 {
	public static void main(String[] args) {
		// ③通过Thread类建立线程对象
		Cat c1 = new Cat("小花猫");// 相当于Thread c11 = new Thread(c1);
		Cat c2 = new Cat("小黑猫");
		// ④调用线程对象的start方法开启线程;
		new Thread(c1).start();
		new Thread(c2).start();
	}
}


(7)比较两种创建线程的方式

继承Thread类:

  • 编写简单,可直接操作线程;
  • 适用于单继承

实现Runnable接口(推荐使用):

  • 避免单继承局限性;
  • 便于共享资源;

(8)线程的五种状态

public class MyRunnable2 implements Runnable {

	public void run() {
		System.out.println("线程t正在运行!");
		try {
			Thread.sleep(500);
			System.out.println("线程t休眠,处于阻塞状态!");
		} catch (InterruptedException e) {
			e.printStackTrace();
			System.out.println("线程t被中断");
		}
	}

	public static void main(String[] args) {
		Thread th = new Thread(new MyRunnable2(), "th");
		System.out.println("线程t处于新建状态!");
		th.start();
		System.out.println("线程t处于就绪状态!");
	}
}

在新建状态可以为线程设置线程名字,优先级;
一旦调用start方法,线程就处于就绪状态;
当获取到cup资源立刻转去调用run()方法执行线程体(此时是运行状态);
运行时可能被阻塞,进程被休眠;
线程执行完毕时,线程就死亡了;
(9)线程优先级

线程调度

按照特定机制为多个线程分配CPU的使用权;

线程调度的方法:
setPriority(int grade);//设置线程优先级
sleep(long millis);//线程休眠(单位毫秒)
join();//线程强制执行(暂停当前线程,直到其他线程执行完毕再执行)
yield();//线程礼让(仅仅是提供一个可能)
设置线程优先级

线程优先级由1~10表示,1最低,默认优先级为5
优先级高的线程获得CPU资源的概率较大

public class Test {
	public static void main(String[] args) {
		Thread t1 = new Thread(new MyRunnable(), "线程A");
		Thread t2 = new Thread(new MyRunnable(), "线程B");
		t1.setPriority(Thread.MAX_PRIORITY);
		t1.setPriority(Thread.MIN_PRIORITY);
		t1.start();
		t2.start();
	}
}

public class MyRunnable implements Runnable {

	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println(Thread.currentThread().getName() + ":" + i);
		}
	}
}

这样后,线程A的优先级会明显变高,线程B的优先级变低

(10)线程休眠和强制执行
线程休眠

public static void sleep (long millis)

  • 让线程暂时睡眠指定时长,线程进入阻塞状态;
  • 睡眠时间过后线程会再进入可运行状态;
  • 调用sleeo()方法需处理InterruptedException异常;
public class Wait {
	public static void bySec(long s){
		for(int i = 0;i<s;i++)
		{
			System.out.println(i+1+"秒");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
public class Test2 {
	public static void main(String[] args) {
		System.out.println("------------主线程开始休眠------------");
		Wait.bySec(5);//主线程休眠5秒;
		System.out.println("----------主线程休眠结束-----------");
	}
}
}

测试结果:

强制执行

public final void join();
public final void join(long mills); public
final void join(long mills,int nanos);

  • millis:以毫秒为单位的等待时长;
  • nanos:要等待的附加纳秒时长;
  • 需处理InterruptedException异常;
package may_30th;

/** * 测试join() * @author mayn */
public class ThreadJoinDemo {
	public static void main(String[] args) {
		System.out.println("*******线程强制执行*******");
		// 1.创建线程对象;
		Thread temp = new Thread(new MyRunnable(), "temp");
		temp.start();
		for (int i = 0; i < 20; i++) {
			// 当主线程执行到i==5时,暂停主线程,让子线程temp执行完毕之后主线程再执行
			if (i == 5) {
				try {
					temp.join();// 强制执行temp线程
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "运行:" + i);
		}
	}
}
package may_30th;

public class MyRunnable implements Runnable {
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "运行:" + i);
		}
	}
}

测试结果:
开始时主线程和子线程交替执行,当开始强制执行子线程时,主线程休眠,待到子线程执行完毕后,主线程再执行;

(11)线程的礼让(效果不明显)

Public static void yield();

  • 暂停当前线程,允许其他具有相同优先级的线程获得运行机会;
  • 该线程处于就绪状态,不转为阻塞状态;
  • 只是提供一种可能,但是不能保证一定会实现礼让;

线程礼让测试:

package may_31th;

public class MyRunnable implements Runnable {
	public void run() {
		for (int i = 0; i < 5; i++) {
			System.out.println(Thread.currentThread().getName() + "运行:" + i);
			// 当i==3时,线程礼让,当前线程将cpu资源让出;
			if (i == 3) {
				Thread.yield();
				System.out.print("线程礼让:");
			}
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

package may_31th;

public class Test {
	public static void main(String[] args) {
		Thread t1 = new Thread(new MyRunnable(), "线程A");
		Thread t2 = new Thread(new MyRunnable(), "线程B");
		t1.start();
		t2.start();
	}
}

测试结果:
结果显示:开始时线程AB交替运行,当B运行到三时,开始礼让,线程A得到了cpu资源,运行一次后也到了3,线程A开始礼让,走线程B…

(12)线程中断

interrupt()线程中断执行;

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务