多线程概述(1)
1.多线程的运行原理
(1)多线程概述
提到线程就要提出进程的概念,进程可以说是正在运行的程序,或者更确切的说是当一个程序开始运行的时候,就变成了一个进程,进程是系统进行资源分配和调度的一个单位。
而线程就是进程中的一个执行单元,负责当前进程中程序的执行。一个程序运行后至少有一个进程,一个进程中至少会有一个线程,另外一个进程中可以有多个线程,这样的程序就是多线程程序。
(2)多线程的运行原理
大多数操作系统都支持多进程并发运行,现在的操作系统几乎都支持同时运行多个任务,其实这些软件在某一时刻,只会运行一个进程。由于cpu在高速切换而导致的。对于CPU而言,它在某个时间点上,只能执行一个程序,CPU不断地在这些进程中切换。由于CPU执行速度对我们而言速度很快,所以在我们看来就是多个进程同时执行。
2.线程的创建
(1)主线程
在程序运行中一定会有一个执行线程从main方法开始的。一直执行到main方法结束。这个线程在java中称之为主线程。当主线程在这个程序中执行时,如果遇到了循环而导致程序在指定位置停留时间过长,无法执行下面的程序,而多线程就可以解决这个问题,一个主线程负责执行其中一个循环,由另一个线程负责其他代码的执行。
(2)继承Thread类创建线程
步骤
- 定义一个类继承Thread;
- 重写run()方法;
- 创建子类对象,就是创建线程对象;
- 调用start方法,开启线程并让线程开始执行,同时系统层面告诉jvm去调用run方法。
举例
class Demo extends Thread{//继承了Thread类
String name;
Demo(String name){
this.name = name;
}
public void run(){
for (int i = 1;i<=20;i++){
System.out.println(name+"i="+i);
}
}
}
public class Demo01{
public static void main(String[] args) {
Demo d1 = new Demo("小徐");
Demo d2 = new Demo("小张");
d1.run();//仅仅只是主线程调用了run方法,并没有开启新的线程
d1.start();//开启一个线程
d2.start();
}
}
在上述代码中如果仅仅调用run方法,并不会开启线程,只是主线程在main里调用了run方法而已。
创建线程的目的
建立了单独的执行路径,让多部分代码实现同时执行。自定义线程需要执行的任务都定义在run方法里,但是Thread类中本身的run方法又不一定是我们需要的,而Thread类已经定义了线程任务的位置,只要定义位置中定义任务代码就可以了,然后重写run方法。
(3)实现Runnable接口创建线程
步骤
- 定义类实现Runnable接口;
- 覆盖接口中的run方法;
- 创建Thread类的对象;
- 将Runnable接口的子类对象作为参数传递给Thread类的构造函数;
- 调用Thread类的start方法开启线程;
举例
class Demo implements Runnable{
String name;
Demo(String name){
this.name = name;
}
public void run(){
for (int i = 1;i<=20;i++){
System.out.println(name+"..."+Thread.currentThread().getName()+"..."+i);
}
}
}
public class Demo01{
public static void main(String[] args) {
Demo d = new Demo("小徐");//此处不是线程对象,只是创建了Runnable子类的对象
//创建Thread类的对象,将Runnable接口的子类对象作为参数传递给Thread类的构造函数
Thread t1 = new Thread(d);
Thread t2 = new Thread(d);
t1.start();//线程启动
t2.start();
}
}
与继承Thread类创建的线程的区别
实现Runnable接口,避免了继承Thread类的单继承局限性。覆盖Runnable接口中的run方法,将线程任务代码实现到run方法中,创建Thread类的对象,只有创建Thread类的对象才可以创建线程。
实现Runnable接口的好处
线程分为两部分,一部分线程对象,一部分线程任务。继承Thread类,线程对象和线程任务耦合在一起。一旦创建了Thread类的子类对象,即使线程对象,又是线程任务。实现Runnable接口,将线程任务单独分离出来封装成对象,类型就是Runnable接口类型。
3.关于多线程的应用(售票)
对于这种多线程同步进行,且共享同一对象(票),可以用实现Runnable接口的方式创建多线程。
class Demo implements Runnable{
private int tickets = 100;
public void run(){
while (true){
if (tickets>0){
System.out.println(Thread.currentThread().getName()+"正在发售第"+tickets--+"张票");
}
}
}
}
public class Demo01{
public static void main(String[] args) {
Demo d = new Demo();//创建实例对象
Thread t1 = new Thread(d,"售票窗口1");
Thread t2 = new Thread(d,"售票窗口2");
Thread t3 = new Thread(d,"售票窗口3");
Thread t4 = new Thread(d,"售票窗口4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}