多线程是Java中的并发机制,表示能够在同一时间内同时执行多个操作。在日常生活中,你边上网边听歌边打游戏(先不管能不能做到)就是一个多线程。但是我们会先入为主的认为这其实是电脑在同一个时间点完成不同的事,就好比一手画圆一手画方。然后其实不是,同时画完方圆也是不太可能的,毕竟人也就只有一个大脑,再极端点来说人不够同时完成睁眼和睡着两个动作,睁一眼闭一眼的好好审题嗷。 电脑也一样,一台电脑的CPU就是一个脑袋,每次只能做一件事情,要么播歌,要么开游戏,轮到谁执行就执行,只是因为电脑运行速度之快以至于让人肉眼感觉不到罢了。那随着CPU进入双核,甚至多核时代,多线程的优势就越来越明显。
在计算机中,每个事件的运行都可以看作是一条线程的运行,在同一时刻(注意,不是同一时间点)有可能在执行多个线程,这样能够更好地提高办事效率。实际开发中也是很多地方使用多线程的,例如在注册QQ时,一方面会通知用户已经注册成功,一方面向用户在注册时填写的手机号或者E-mail中发送邮件。这里就需要使用多线程,如果使用单线程的话系统就得在向用户注册时填写的手机号或E-mail中发送邮件后才可以显示用户注册成功,由于发送的过程可能需要很长的时间,从而影响整条注册线程的速度。
每一个程序中的main方法其实就是一个线程,一般称为主线程。在主线程中可以启动多个子线程来执行。
定义线程的方法
1.继承Thread类 定义线程
定义一个线程可以通过继承Thread类来实现,这是一种相对简单的定义线程的方法。在Thread类中有一个run方法,在定义的线程中需要重写这个方法。在重写的run方法中,可以定义该线程所需要执行的语句。当线程启动时,run方法中的程序就成为一条独立的执行线程。
public class xianCheng1 extends Thread {
public void run() {
System.out.peintln("通过继承Thread定义线程");
}
}
//重写的run方法也可以作为一般仿佛来调用,但这种调用并不作为一个线程出现,他只是主线程中的一部分。同样,run方法也是可以被重载的,但是重载后的run方法不作为一个线程,而是主线程的一部分。
//创建线程
/**
*XianCheng1 xc = new XianCheng1();
*/
2.实现Runnable接口 定义线程
定义线程除了通过继承Thread类来实现,还可以通过Runnable接口来实现。在Runnable接口中具有一个抽象的run方法,在实现Runnable接口时,需要实现该run方法。该run方法就会作为一个执行线程的方法
public class XianCheng2 implements Runnable {
public void run() {
System.out.println("通过实现Runnable接口定义线程");
}
}
//这两种方法都需要定义一个run方法,不管该方法是通过重写父类方法还是实现接口类方法。run方法是一个线程的入口,是线程必须有的。
//直接创建类对象,创建的并不是一个线程对象。要想创建线程对象,必须要借助Thread类。
/**
*创建线程对象的程序如下所示
*XianCheng2 xc = new XianCheng();
*Thred t = new Thread(xc);
*/
在程序中,run方法是可以通过方法调用来执行的,但是这并不代表创建了一个新的线程。直接 对象.run(); 是一个错误的启动线程的方法
如果像正确地启动一个线程,需要调用的是线程对象的start方法,如下所示
class MyRunnable implements Runnable
{
//定义一个run线程方法
public void run()
{
System.out.println("这是一个正确的启动线程的程序");
}
}
public class XianCheng3
{
public class XianCheng3
{
MyRunnable mr = new MyRunnable();
Thread t = new Thread(mr);
t.start();//启动线程
}
}
同时运行多个线程
//定义一个实现Runnable接口的类
class MyRunnable1 implements Runnable {
//定义一个run线程方法
public void run() {
for(int i=0;i<100;i++) {
System.out.print("@);
}
}
}
//再定义一个实现Runnable接口的类
class MyRunnable2 implements Runnable {
//定义一个run线程方法
public void run() {
for(int i=0;i<100;i++) {
System.out.print("$");
}
}
}
public class XianCheng4 {
public static void main(String args[]) {
MyRunnable1 mr1 = new MyRunnable1();
MyRunnable2 mr2 = new MyRunnable2();
Thread t1 = new Thread(mr1);
Thread t2 = new Thread(mr2);
t1.start(); //启动第一个线程
t2.start(); //启动第二个线程
}
}
//在同时执行多个线程时,运行结果不是唯一的,因为有很多不确定的因素。首先先执行那一条线程就是不确定的,线程之间交替也是不确定的。但是确定的是每一个线程都将启动,每一个线程都会执行结束。
线程生命周期
线程是存在生命周期的,分为五个不同状态————新建——准备——运行——等待/阻塞——死亡
- 新建状态:当一个线程对象被创建后,线程就处于新建状态。
- 准备状态:处于新建状态的线程被调用start方法就会进入准备状态。
- 运行状态:处于准备状态的线程一旦被系统选中,使得线程获取了CPU时间。就会进入运行状态。多核CPU可能同时使两个或更多线程处于运行状态。
- 等待/阻塞状态:睡眠、阻塞、挂起和等待就是线程在处于等待/阻塞状态,处于该状态的线程被解除后不会立即回到运行状态,而是首先进入准备状态,等待系统的调度。
- 死亡状态:当线程的run方法执行结束后,或者程序发生异常终止运行后,线程就会进入死亡状态。线程是无私的,是不求回报的,是伟大的(狗头)。
睡眠方法
当线程处于运行状态是,调用sleep睡眠方法将使线程从运行状态进入等待/阻塞状态,从而是程序停止运行。
sleep方法被重载,存在两种形式,sleep方法的基本语法格式如下所示。
//mills参数表示线程睡眠的毫秒数
public static void sleep(long millis)throws InterruptedException;
//nanos参数表示线程睡眠的纳秒数
public static void sleep(long millis,int nanos)throws InterruptedException
//要想让某一个线程进入睡眠状态,并不是让该线程调用sleep方法,只是让该线程执行sleep方法。
//sleep方法是可能发生捕获异常的,所以在使用sleep方法时必须进行异常处理。
实例代码如下:
//定义一个实现的Runnable接口的类
class MyRunnable implements Runnable {
//定义一个run线程的方法
public void run() {
for(int i=0;i<100;i++) {
System.out.print("@");
try {
Thread.sleep(100); //使用sleep方法使线程进入100毫秒的睡眠状态
} cactch(InterruptedException e) {
e.printStackTracce();
}
}
}
}
//再定义一个实现Runnable接口的类
class MyRunnable2 implements Runnable {
//定义一个run线程的方法
public void run() {
for(int i=0;i<100;i++) {
System.out.print("$");
try {
Thread.sleep(100); //同上
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class XianCheng5 {
public static void main(String args[]) {
MyRunnable mr1 = new MyRunnable1();
MyRunnable mr2 = new MyRunnable2();
Thread t1 = new Thread(mr1);
Thread t2 = new Thread(mr2);
t1.start(); //启动第一个线程
t2.start(); //启动第二个线程
}
}
线程优先级
Java中的优先级是采用1到10来表示的,数字越大表示优先级越高。如果没有为线程设置优先级,则线程的优先级为5(默认值)。
当需要对线程的优先级进行设置时,可以通过调用setPriority方法来设置,语法格式如下所示:
public final void setPriority(int i);
除此之外,Java在Thread类中还定义了三个表示优先级的常量。
MAX_PRIORITY表示线程最高级
NORM_PRIORITY表示线程的默认优先级
MIN_PRIORITY表示线程的最低优先级
t1.setPriority(Thread.MAX_PRIORITY)
t2.setPriority(Thread.NORM_PRIORITY)
t3.setPriority(Thread.MIN_PRIORITY)
先更新这么多,下次还会持续更新,多谢大家捧场~