创建多线程的几种方式
多线程的形式上实现方式主要有两种,一种是继承Thread类,一种是实现Runnable接口。本质上实现方式都是来实现线程任务,然后启动线程执行线程任务(这里的线程任务实际上就是run方法)。
继承Thread类
实现线程的第一种方式就是继承Thread类的方式。继承Thread类是最简单的一种实现线程的方式,通过jdk给我们提供的Thread类,重写Thread类的run方法即可,那么当线程启动的时候,就会执行run方法体的内容。
public class ThreadDemo extends Thread {
@Override
public void run() {
while (true) {
System.out.println(Thread.currentThread().getName() + " is running ... "); // 打印当前线程的名字
try {
Thread.sleep(1000); // 休息1000ms
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ThreadDemo td = new ThreadDemo();
td.start(); // 启动线程
while (true) {
System.out.println(Thread.currentThread().getName() + " is running ... "); // 打印当前线程的名字
try {
Thread.sleep(1000); // 休息1000ms
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
实现Runnable接口
实现Runnable接口也是一种常见的创建线程的方式。使用接口的方式可以让我们的程序降低耦合度。其实Runnable就是一个线程任务,线程任务和线程的控制分离,这也就是上面所说的解耦。我们要实现一个线程,可以借助Thread类,Thread类要执行的任务就可以由实现了Runnable接口的类来处理。 这就是Runnable的精髓之所在!
使用Runnable实现上面的例子步骤如下
定义一个类实现Runnable接口,作为线程任务类
重写run方法,并实现方法体,方法体的代码就是线程所执行的代码
定义一个可以运行的类,并在main方法中创建线程任务类
创建Thread类,并将线程任务类做为Thread类的构造方法传入
启动线程
public class ThreadTarget implements Runnable {
@Override
public void run() {
while(true) {
System.out.println(Thread.currentThread().getName() + " is running .. ");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
使用内部类的方式
这并不是一种新的实现线程的方式,只是另外的一种写法。比如有些情况我们的线程就想执行一次,以后就用不到了。那么像上面两种方式都还要再定义一个类,显得比较麻烦,我们就可以通过匿名内部类的方式来实现。使用内部类实现依然有两种,分别是继承Thread类和实现Runnable接口
public class DemoThread {
public static void main(String[] args) {
// 基于子类的实现
new Thread() {
public void run() {
while (true) {
System.out.println(Thread.currentThread().getName() + " is running ... "); // 打印当前线程的名字
try {
Thread.sleep(1000); // 休息1000ms
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}.start();
// 基于接口的实现
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println(Thread.currentThread().getName() + " is running ... "); // 打印当前线程的名字
try {
Thread.sleep(1000); // 休息1000ms
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
// 主线程的方法
while (true) {
System.out.println(Thread.currentThread().getName() + " is running ... "); // 打印当前线程的名字
try {
Thread.sleep(1000); // 休息1000ms
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
定时器
定时器可以说是一种基于线程的一个工具类。可以定时的来执行某个任务。比如要在凌晨的时候汇总一些数据,比如要每隔10分钟抓取一次某个网站上的数据等等,总之计时器无处不在。我们一般将需要定时完成的任务称之为计划任务,这在很多的系统中是非常常见的,比如linux的计划任务,比如Windows下的任务计划等等。我们自己的系统中也需要很多定时执行的也都需要计划任务。最简单的计划任务就可以通过jdk给我提供的API来实现,当然也有很多的计划任务的框架,比如spring的schedule以及著名的quartz。我们这里不去讨论其他的计划任务框架,我们就来看一下jdk所给我们提供的API来实现定时任务。
public class TimerDemo {
private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
public static void main(String[] args) throws Exception {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("定时任务执行了....");
}
}, format.parse("2017-10-11 22:00:00"));
}
}
基于线程池的方式
我们知道,线程和数据库连接这些资源都是非常宝贵的资源。那么每次需要的时候创建,不需要的时候销毁,是非常浪费资源的。那么我们就可以使用缓存的策略,也就是使用线程池。当然了,线程池也不需要我们来实现,jdk的官方也给我们提供了API
public static void main(String[] args) {
// 创建线程池
ExecutorService threadPool = Executors.newFixedThreadPool(10);
while(true) {
threadPool.execute(new Runnable() { // 提交多个线程任务,并执行
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " is running ..");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
上一篇: Python实现有理数的四则运算
下一篇: 多线程问题分析thread