Java多线程初体验

一、什么是多线程?

线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。具有这种能力的系统包括对称多处理机、多核心处理器以及芯片级多处理(Chip-level multithreading)或同时多线程(Simultaneous multithreading)处理器。在一个程序中,这些独立运行的程序片段叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理(Multithreading)”。
——《百度百科》

二、怎么创建Java多线程

在Java语言中,关于线程的类有Thread类,关于多线程的接口有Runnable和Callable接口(JDK1.5新增),要在Java中实现多线程,则必须实现对应的接口或继承对应的类。

方法一:继承Thread类

步骤:

  1. 创建一个类继承Thread类
  2. 重写Thread类中的run()方法
  3. 创建Thread类的子类的对象
  4. 通过对象调用start()方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
java复制代码public class ThreadTest{
public static void main(String[] args) {
//3.创建Thread类的子类的对象
MyThread t1 = new MyThread();
//4.通过对象调用start()方法
t1.start();
//3.创建Thread类的子类的对象
MyThread t2 = new MyThread();
//4.通过对象调用start()方法
t2.start();
}
}
//1.创建一个类继承Thread类
class MyThread extends Thread{
//2.重写Thread类中的run()方法
@Override
public void run() {
for(int i = 0; i < 100; i++){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}

多线程可以创建多个Thread类的子类的对象,每一个对象就是一个线程,每一个线程分别调用自己的start()方法。

方法二:实现Runnable接口

步骤:

  1. 创建一个实现了Runnable接口的类
  2. 实现Runnable接口中的run()方法
  3. 创建实现类的对象
  4. 将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
  5. 通过Thread类的对象调用start()方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
java复制代码//1. 创建一个实现了Runnable接口的类
class MThread implements Runnable{
//2. 实现Runnable接口中的run()方法
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}

public class RunnableTest {
public static void main(String[] args) {
//3. 创建实现类的对象
MThread m1 = new MThread();
//4. 将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
Thread thread = new Thread(m1);
//5. 通过Thread类的对象调用start()方法。
thread.start();
Thread thread1 = new Thread(m1);
thread1.start();
}
}

使用实现Runnable接口的方法创建多线程,实现了Runnable接口的类只需要实例化一个对象即可,将对象传入到Thread类的构造器中,创建多个不同的Thread类,每一个Thread类的对象就是一个线程。

方法三:实现Callable接口(JDK1.5新增)

步骤:

  1. 创建一个实现Callable接口的实现类
  2. 实现Callable接口的call()方法,将此线程需要执行的操作声明在该方法中
  3. 创建Callable接口实现类的对象
  4. 将Callable实现类的对象作为参数传递到FutureTask构造器中,创建FutureTask的对象
  5. 将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread类的对象,并调用start()方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
java复制代码//1. 创建一个实现Callable接口的实现类
class NumThread implements Callable{
//实现Callable接口的call()方法,将此线程需要执行的操作声明在该方法中
@Override
public Object call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
System.out.println(i);
sum += i;
}
return sum;
}
}
public class ThreadNew {
public static void main(String[] args) {
//3. 创建Callable接口实现类的对象
NumThread numThread = new NumThread();
//4. 将Callable实现类的对象作为参数传递到FutureTask构造器中,创建FutureTask的对象
FutureTask futureTask1 = new FutureTask(numThread);
//5. 将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread类的对象,并调用start()方法
new Thread(futureTask1).start();
FutureTask futureTask2 = new FutureTask(numThread);
new Thread(futureTask2).start();
try {
//get()方法的返回值即为FutureTask构造器参数Callable实现类重写的call()方法的返回值
Object value = futureTask1.get();
System.out.println(value);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}

使用该方法实现多线程的好处是多线程的具体方法可以有返回值,使用FutureTask类的对象的get()方法可以获取到call()方法的返回值。
该方法多线程只需要创建一个实现Callable接口的对象,将对象传入到FutureTask中创建多个FutureTask类的对象,再将FutureTask对象传入到Thread类中生成Thread类的对象,每一个Thread类的对象就是一个线程。

方法四:使用线程池

步骤:

  1. 提供一个实现了Runnable或Callable接口的类,并重写其中的run()或call()方法
  2. 提供指定线程数量的线程池
  3. 执行指定线程的操作,需要提供实现Runnable接口或Callable接口实现类的对象
  4. 关闭连接池
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
java复制代码//1. 提供一个实现了Runnable或Callable接口的类,并重写其中的run()或call()方法
class NumThread implements Runnable{
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if(i % 2 == 0){
System.out.println(i);
}
}
}
}
public class ThreadPool {
public static void main(String[] args) {
//1.提供指定线程数量的线程池
ExecutorService service = Executors.newFixedThreadPool(10);
//2.执行指定线程的操作,需要提供实现Runnable接口或Callable接口实现类的对象
service.execute(new NumThread()); //适用于Runnable
// service.submit(); //适用于Callable
//3.关闭连接池
service.shutdown();
}
}

使用线程池的优点:

  1. 提高响应速度(减少了创建线程的时间)
  2. 降低资源消耗(重复利用线程池中的线程,不需要每次使用都创建)
  3. 便于线程管理

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%