多线程01

进程:进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。

 

线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。

 

简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程

 

程序运行的原理

 

分时调度

 

所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。

 

抢占式调度

 

优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性)Java使用的为抢占式调度。

 

大部分操作系统都支持多进程并发运行,现在的操作系统几乎都支持同时运行多个程序。比如:现在我们上课一边使用编辑器,一边使用录屏软件,同时还开着画图板,dos窗口等软件。此时,这些程序是在同时运行,感觉这些软件好像在同一时刻运行着

 

实际上,CPU(中央处理器)使用抢占式调度模式在多个线程间进行着高速的切换。对于CPU的一个核而言,某个时刻,只能执行一个线程,而 CPU的在多个线程间切换速度相对我们的感觉要快,看上去就是在同一时刻运行。

 

其实,多线程程序并不能提高程序的运行速度,但能够提高程序运行效率,让CPU的使用率更高。

 

 

主线程

 

jvm启动后,必然有一个执行路径(线程)main方法开始的,一直执行到main方法结束,这个线程在java中称之为主线程。当程序的主线程执行时,如果遇到了循环而导致程序在指定位置停留时间过长,则无法马上执行下面的程序,需要等待循环结束后能够执行。

 

 

Thread类

基本线程类指的是Thread类,Runnable接口,Callable接口

 

创建新执行线程有两种方法。

 

一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。创建对象,开启线程run方法相当于其他线程的main方法。

 

另一种方法是声明一个实现 Runnable 接口的类。该类然后实现 run 方法。然后创建Runnable的子类对象,传入到某个线程的构造方法中开启线程。

 

创建线程的第一种方法,继承Thread类

代码演示:

测试类

 

public class Demo01 {

 

public static void main(String[] args) {

 

//创建自定义线程对象

 

MyThread mt = new MyThread("新的线程!");

 

//开启新线程

 

mt.start();

 

//在主方法中执行for循环

 

for (int i = 0; i < 10; i++) {

 

System.out.println("main线程!"+i);

 

}

 

}

 

}

 

自定义线程类

 

public class MyThread extends Thread {

 

//定义指定线程名称的构造方法

 

public MyThread(String name) {

 

//调用父类的String参数的构造方法,指定线程的名称

 

super(name);

 

}

 

/**

 

 * 重写run方法,完成该线程执行的逻辑

 

 */

 

@Override

 

public void run() {

 

for (int i = 0; i < 10; i++) {

 

System.out.println(getName()+":正在执行!"+i);

 

}

 

}

 

}

 

创建线程的目的是什么?

是为了建立程序单独的执行路径,让多部分代码实现同时执行。也就是说线程创建并执行需要给定线程要执行的任务。

对于之前所讲的主线程,它的任务定义在main函数中。自定义线程需要执行的任务都定义在run方法中。

Threadrun方法中的任务并不是我们所需要的,只有重写这个run方法。既然Thread类已经定义了线程任务的编写位置(run方法),那么只要在编写位置(run方法)中定义任务代码即可。所以进行了重写run方法动作。

 

获取线程名称的两个方法:

 

l Thread.currentThread()获取当前线程对象

 

l Thread.currentThread().getName();获取当前线程对象的名称

 

 

进行多线程编程时,不要忘记了Java程序运行是从主线程开始,main方法就是主线程的线程执行内容。

 

 

创建线程方式实现Runnable接口

 

创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后创建Runnable的子类对象,传入到某个线程的构造方法中开启线程。

 

Runnable接口用来指定每个线程要执行的任务。包含了一个 run 的无参数抽象方法,需要由接口实现类重写该方法。

 

 

创建线程的步骤。

 

1、定义类实现Runnable接口。

 

2、覆盖接口中的run方法。。

 

3、创建Thread类的对象

 

4、将Runnable接口的子类对象作为参数传递给Thread类的构造函数。

 

5、调用Thread类的start方法开启线程。

 

代码演示:

 

public class Demo02 {

 

public static void main(String[] args) {

 

//创建线程执行目标类对象

 

Runnable runn = new MyRunnable();

 

//Runnable接口的子类对象作为参数传递给Thread类的构造函数

 

Thread thread = new Thread(runn);

 

Thread thread2 = new Thread(runn);

 

//开启线程

 

thread.start();

 

thread2.start();

 

for (int i = 0; i < 10; i++) {

 

System.out.println("main线程:正在执行!"+i);

 

}

 

}

 

}

 

自定义线程执行任务

 

public class MyRunnable implements Runnable{

 

 

 

//定义线程要执行的run方法逻辑

 

@Override

 

public void run() {

 

 

 

for (int i = 0; i < 10; i++) {

 

System.out.println("我的线程:正在执行"+i);

 

}

 

}

 

}

 

 

 

 

 

 

实现Runnable接口,避免了继承Thread类的单继承局限性。

覆盖Runnable接口中的run方法,将线程任务代码定义到run方法

 

实现Runnable接口的方式,更加的符合面向对象,线程分为两部分,一部分线程对象,一部分线程任务。继承Thread类,线程对象和线程任务耦合在一起。一旦创建Thread类的子类对象,既是线程对象,有又有线程任务。实现runnable接口,将线程任务单独分离出来封装成对象,类型就是Runnable接口类型。Runnable接口对线程对象和线程任务进行解耦。

 

线程的匿名内部类使用

使用线程的内匿名内部类方式,可以方便的实现每个线程执行不同的线程任务操作。

方式1:创建线程对象时,直接重写Thread类中的run方法

new Thread() {

public void run() {

for (int x = 0; x < 40; x++) {

System.out.println(Thread.currentThread().getName()

+ "...X...." + x);

}

}

}.start();

 

方式2:使用匿名内部类的方式实现Runnable接口,重新Runnable接口中的run方法

Runnable r = new Runnable() {

public void run() {

for (int x = 0; x < 40; x++) {

System.out.println(Thread.currentThread().getName()

+ "...Y...." + x);

}

}

};

new Thread(r).start();

 

 

 

 

 

 

 

 

posted on 2019-10-14 09:31  小蜘zhu  阅读(92)  评论(0编辑  收藏  举报