Java多线程编程实例攻略
Java多线程编程使得程序可以同时运行多个任务,从而提高程序的效率,降低资源的浪费。本篇攻略将介绍Java多线程编程的基本概念、实例说明和注意事项。
多线程编程的基本概念
- 进程(process):计算机中一个正在运行程序的实例。
- 线程(thread):进程中负责执行任务的单个执行流程。每个进程可以拥有多个线程。
- 并发:多个任务同时执行的情况。
- 并行:多个任务同时执行,且每个任务在不同的处理器核心上运行的情况。
Java多线程编程的实现
Java多线程编程的实现可以通过两种方式:继承Thread类和实现Runnable接口。
继承Thread类
定义一个继承Thread类的子类,并重载类中的run()方法,这个run()方法中包含了线程执行的代码。
class MyThread extends Thread {
public void run() {
// 线程执行的代码
}
}
实现Runnable接口
定义一个实现Runnable接口的类,实现接口中的run()方法。
class MyRunnable implements Runnable{
public void run() {
// 线程执行的代码
}
}
在主函数中启动线程:
Thread t = new Thread(new MyThread());
t.start();
MyRunnable m = new MyRunnable();
Thread t = new Thread(m);
t.start();
可以发现实现Runnable接口的方式有些繁琐,但却更具有灵活性,例如:
- 可以同时实现多个接口;
- 不需要通过继承Thread类来创建线程。
示例说明
示例1: 多线程下载文件
public class Main {
static final int NUM_THREADS = 4;
static final String[] urls = {
"https://img-blog.csdn.net/20180507231500731",
"https://img-blog.csdn.net/20180507231526681",
"https://img-blog.csdn.net/20180507231613441",
"https://img-blog.csdn.net/20180507231637775"
};
public static void main(String args[]) {
ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
for (int i = 0; i < NUM_THREADS; i++) {
executor.execute(new Downloader(urls[i]));
}
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println("所有线程均已完成下载");
}
}
class Downloader implements Runnable {
private final String url;
public Downloader(String url) {
this.url = url;
}
public void run() {
System.out.println("正在下载文件:" + url);
try {
URL u = new URL(url);
InputStream in = u.openStream();
byte[] buffer = new byte[1024];
int len = 0;
OutputStream out = new FileOutputStream(getFilename(u));
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("下载文件完成:" + url);
}
private String getFilename(URL u) {
String filename = u.getPath();
return filename.substring(filename.lastIndexOf('/') + 1);
}
}
运行结果:
正在下载文件:https://img-blog.csdn.net/20180507231500731
正在下载文件:https://img-blog.csdn.net/20180507231637775
正在下载文件:https://img-blog.csdn.net/20180507231526681
正在下载文件:https://img-blog.csdn.net/20180507231613441
下载文件完成:https://img-blog.csdn.net/20180507231637775
下载文件完成:https://img-blog.csdn.net/20180507231613441
下载文件完成:https://img-blog.csdn.net/20180507231526681
下载文件完成:https://img-blog.csdn.net/20180507231500731
所有线程均已完成下载
示例2: 生产者 - 消费者模型
public class Main {
public static void main(String args[]) {
BlockingQueue<Integer> sharedQueue = new LinkedBlockingQueue<>();
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.execute(new Producer(sharedQueue));
executor.execute(new Consumer(sharedQueue));
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println("所有线程均已完成任务");
}
}
class Producer implements Runnable {
private final BlockingQueue<Integer> sharedQueue;
public Producer(BlockingQueue<Integer> sharedQueue) {
this.sharedQueue = sharedQueue;
}
public void run() {
for (int i = 1; i <= 10; i++) {
try {
sharedQueue.put(i);
System.out.println("生产者生产:" + i);
Thread.sleep(100);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
private final BlockingQueue<Integer> sharedQueue;
public Consumer(BlockingQueue<Integer> sharedQueue) {
this.sharedQueue = sharedQueue;
}
public void run() {
while (true) {
try {
Integer value = sharedQueue.take();
System.out.println("消费者消费:" + value);
Thread.sleep(300);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
运行结果:
生产者生产:1
消费者消费:1
生产者生产:2
消费者消费:2
生产者生产:3
消费者消费:3
生产者生产:4
消费者消费:4
生产者生产:5
消费者消费:5
生产者生产:6
消费者消费:6
生产者生产:7
消费者消费:7
生产者生产:8
消费者消费:8
生产者生产:9
消费者消费:9
生产者生产:10
消费者消费:10
注意事项
- 当多个线程操作共享对象时,可能会出现数据竞争和死锁的情况,需要通过线程同步来解决。
- 在使用wait()和notify()函数时,必须要获得锁对象的所有权。
- 通过使用线程池来管理线程可以提高程序的性能。
- 程序中的睡眠时间、阻塞操作时间应当合理使用,否则可能会影响程序的响应性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java多线程编程实例 - Python技术站