欢迎来到Java线程示例。 进程 和 线程 是两个基本的执行单元。并发编程更关注于Java线程。
进程
A process is a self contained execution environment and it can be seen as a program or application. However a program itself contains multiple processes inside it. Java runtime environment runs as a single process which contains different classes and programs as processes.
线程
线程可以被称为 轻量级进程。线程需要较少的资源来创建并存在于进程中,线程共享进程资源。
Java线程示例
每个Java应用程序至少有一个线程 – 主线程。虽然还有许多其他后台运行的Java线程,如内存管理、系统管理、信号处理等。但从应用程序的角度来看 – 主线程是第一个Java线程,我们可以从它创建多个线程。多线程是指两个或多个线程在单个程序中同时执行。计算机单核处理器一次只能执行一个线程,而时间切片是操作系统在不同进程和线程之间共享处理器时间的功能。
Java线程的优势
- 与进程相比,Java线程轻量级,创建线程所需的时间和资源较少。
- 线程共享其父进程的数据和代码
- 线程之间的上下文切换通常比进程之间的切换开销小。
- 线程间通信相对比进程间通信更容易。
Java提供两种创建线程的方式。
- 通过实现java.lang.Runnable接口。
- 通过扩展java.lang.Thread类。
Java 线程示例 – 实现 Runnable 接口
要使一个类可运行,我们可以实现 java.lang.Runnable 接口,并在 public void run()
方法中提供实现。要将此类用作线程,我们需要通过传递此可运行类的对象来创建一个 Thread 对象,然后调用 start()
方法以在单独的线程中执行 run()
方法。这是一个通过实现 Runnable 接口的 Java 线程示例。
package com.journaldev.threads;
public class HeavyWorkRunnable implements Runnable {
@Override
public void run() {
System.out.println("Doing heavy processing - START "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
//获取数据库连接,从数据库中删除未使用的数据
doDBProcessing();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Doing heavy processing - END "+Thread.currentThread().getName());
}
private void doDBProcessing() throws InterruptedException {
Thread.sleep(5000);
}
}
Java 线程示例 – 扩展 Thread 类
我们可以扩展 java.lang.Thread 类来创建自己的 Java 线程类,并重写 run()
方法。然后我们可以创建它的对象并调用 start()
方法来执行我们自定义的 Java 线程类的 run 方法。这是一个简单的 Java 线程示例,展示了如何扩展 Thread 类。
package com.journaldev.threads;
public class MyThread extends Thread {
public MyThread(String name) {
super(name);
}
@Override
public void run() {
System.out.println("MyThread - START "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
//获取数据库连接,从数据库中删除未使用的数据
doDBProcessing();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("MyThread - END "+Thread.currentThread().getName());
}
private void doDBProcessing() throws InterruptedException {
Thread.sleep(5000);
}
}
这是一个测试程序,展示了如何创建一个 Java 线程并执行它。
package com.journaldev.threads;
public class ThreadRunExample {
public static void main(String[] args){
Thread t1 = new Thread(new HeavyWorkRunnable(), "t1");
Thread t2 = new Thread(new HeavyWorkRunnable(), "t2");
System.out.println("Starting Runnable threads");
t1.start();
t2.start();
System.out.println("Runnable Threads has been started");
Thread t3 = new MyThread("t3");
Thread t4 = new MyThread("t4");
System.out.println("Starting MyThreads");
t3.start();
t4.start();
System.out.println("MyThreads has been started");
}
}
上述 Java 线程示例程序的输出是:
Starting Runnable threads
Runnable Threads has been started
Doing heavy processing - START t1
Doing heavy processing - START t2
Starting MyThreads
MyThread - START Thread-0
MyThreads has been started
MyThread - START Thread-1
Doing heavy processing - END t2
MyThread - END Thread-1
MyThread - END Thread-0
Doing heavy processing - END t1
一旦我们启动任何线程,其执行取决于时间片切换的操作系统实现,我们无法控制它们的执行。但是,我们可以设置线程的优先级,但即使这样,也不能保证较高优先级的线程将首先执行。多次运行上述程序,你会发现线程启动和结束没有任何模式。
可运行 vs 线程
如果你的类提供的功能比仅作为线程运行更多,你应该实现 Runnable 接口以提供一种作为线程运行的方式。如果你的类的唯一目标是作为线程运行,你可以扩展 Thread 类。实现 Runnable 更可取,因为 Java 支持实现多个接口。如果你扩展 Thread 类,就不能扩展其他任何类。提示:正如你注意到的,线程不返回任何值,但是如果我们希望我们的线程执行一些处理,然后将结果返回给我们的客户端程序,可以查看我们的Java Callable Future。更新:从 Java 8 开始,Runnable 是一个函数接口,我们可以使用 lambda 表达式提供其实现,而不是使用匿名类。有关更多详细信息,请查看Java 8 函数接口。
Source:
https://www.digitalocean.com/community/tutorials/java-thread-example