标签:区别 setdaemon ati 自动 构造 有一个 接口实现 存在 private
在操作系统中,每个独立执行的程序都可称为一个进程,也就是 “正在运行的程序”。
实际上,进程不是同时运行的,对于一个 CPU 而言,某个时间段只能运行一个程序,也就是只能执行一个进程。操作系统会为每个进程分配一段有限的 CPU 使用时间,CPU 在这段时间内执行某个进程,然后会在下一段时间切换到另一个进程中去执行。
在一个进程中还可以有多个执行单元同时运行,这些执行单元被称为线程。
操作系统中至少存在一个线程。
多线程成语运行时,每个线程之间都是独立的,他们可以并发执行。和进程一样,也是由CPU轮流执行的。
每个进程都有独立的代码和数据空间。线程可以看成是轻量级的进程,属于同一进程的线程共享代码和数据空间。
最根本区别:进程是资源分配的单位,线程是调度和执行的单位。
多进程:在操作系统中能同时运行多个任务(程序)。
多线程:在同一应用程序中有多个顺序流同时进行。
Java 提供了两种多线程实现方式,一种是继承 java.lang 包下的 Thread 类;另一种是实现 java.lang.Runnable 接口。
JDK 中提供了一个线程类 Thread,通过继承 Thread 类,并重写 Thread 类中的 run() 方法便可实现多线程。
在 Thread 类中,提供了一个 start() 方法用于启动新线程,线程启动后,系统会自动调用 run() 方法。
【例1-1】实现一个简单的多线程
public class Example01 { public static void main(String[] args) { MyThread mt = new MyThread(); mt.start(); while (true) { System.out.println("main()方法正在运行"); } } } class MyThread extends Thread { public void run() { while (true) { System.out.println("Mythread()的run()方法正在运行。"); } } }
运行结果如下:
从图中的运行结果可以看出,两个 while 循环中的打印语句轮流执行。说明该实例实现了多线程。
Thread 有个缺陷:Java 中只支持单继承,一个类如果继承了某个父类就不能再继承 Thread 类了。为了克服弊端,Thread 类提供了另一个构造方法 Thread(Runnable target),该方法中,Runnable 是一个接口,它只有一个 run() 方法。当应用时,只需要为该方法提供一个实现了 Runnable 接口的实例对象,这样创建的线程将调用实现了 Runnable 接口中的 run() 方法作为运行代码。
【例2-1】Runnable 接口实现多线程
public class Example02 { public static void main(String[] args) { MyThread2 mt = new MyThread2(); Thread thread = new Thread(mt); thread.start(); while (true) { System.out.println("main()方法正在运行。"); } } } class MyThread2 implements Runnable { @Override public void run() { //当调用start()方法时,线程从此处开始执行 while (true) { System.out.println("MyThread类的run()方法正在运行。"); } } }
运行结果如下:
MyThread 类实现了 Runnable 接口,并重写了 Runnable 接口中的run() 方法,通过 Thread 类的构造方法将 MyThread 类的实例对象作为参数传入。由运行结果可以看出,实现了多线程。
实现 Runnable 接口相对于继承 Thread 类来说,有如下好处:
适合多个相同程序代码的线程处理同一个资源的情况。
避免 Java 单继承带来的局限性。
【例2-2】使用 Runnable 实现四个售票窗口同时售票
public class Example03 { public static void main(String[] args) { TicketWindow tw = new TicketWindow(); new Thread(tw, "窗口1").start(); new Thread(tw, "窗口2").start(); new Thread(tw, "窗口3").start(); new Thread(tw, "窗口4").start(); } } class TicketWindow implements Runnable { private int tickets = 100; @Override public void run() { while (true) { if (tickets >= 0) { Thread th =Thread.currentThread(); String th_name = th.getName(); System.out.println(th_name + ":正在发售第 " + tickets-- + " 张票"); } } } }
运行结果如下:
示例2-2中只创建了一个 TicketWindow 对象,然后创建了四个线程,在每个线程上都去调用这个 TicketWindow 对象中的 run() 方法,这样就可以确保四个线程访问的是同一个 tickets 变量,共享100张票。
新创建的线程默认都是前台线程,如果某个线程对象再启动之前调用了 setDaemon(true) 语句,这个线程就变成了一个后台线程。
如果一个进程中只有后台线程运行,这个进程就会结束。
(待续)
标签:区别 setdaemon ati 自动 构造 有一个 接口实现 存在 private
原文地址:https://www.cnblogs.com/zzfan/p/11039699.html