线程的基本使用
Posted XeonYu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程的基本使用相关的知识,希望对你有一定的参考价值。
上一篇 多线程的基本概念
了解完多线程的概念之后,我们先来看一下线程的基本使用。
Java线程的两种实现方式
Java中实现线程的方式有两种
- 继承自Thread类,在子类实现run方法
- 实现Runnable接口,重写run方法
我们先来简单看看Thread类
Thread类实现了Runnable接口
Runnable接口中只有一个run方法,实际上,线程的任务就是在run方法中执行的,也就是说我们实际开发过程中就是在run方法里写业务代码。
方式一:继承Thread类
public class MyWorkThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "执行任务。。。" + i);
}
}
}
public class TestJava {
public static void main(String[] args) {
/*创建子线程*/
MyWorkThread myWorkThread = new MyWorkThread();
/*启动myWorkThread*/
myWorkThread.start();
/*主线程打印*/
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "执行任务。。。" + i);
}
}
}
运行结果如下:
一般我们不会使用这种方式去实现多线程,因为这种写法比较死板,定义好的线程只能实现固定的写好的任务。
方式二:实现Runable接口
package methord2;
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("MyRunnable" + i);
}
}
}
package methord2;
public class Test {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
for (int i = 0; i < 100; i++) {
System.out.println("main :" + i);
}
}
}
运行结果:
通过匿名内部类简化代码:
可以看到 Thread 构造接收的Runnable是个接口,那我们可以使用匿名内部类来简化一下代码,如下:
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("Runnable" + i);
}
}
});
thread.start();
通过Lambda表达式简化代码
由于Runnable接口中只有一个方法,那我们还可以直接写成Lambda的方式,代码如下
Thread thread = new Thread(() -> {
for (int i = 0; i < 100; i++) {
System.out.println("Runnable" + i);
}
});
thread.start();
这样一来,相比方式一,代码就简洁很多了,而且更加灵活。
Kotlin的写法就更简单了,如下:
fun main() {
/*创建线程并启动*/
Thread {
for (i in 1..100) {
println("${Thread.currentThread().name}=========>${i}")
}
}.start()
/*主线程*/
for (i in 1..100) {
println("${Thread.currentThread().name}=========>${i}")
}
}
运行结果:
Runnable接口中的run方法是没有返回值的,如果我们想获取线程执行的返回结果,可以使用Callable
先看下Callable接口,可以看到,Callable接口接收一个泛型,实际执行的方法是call方法,且这个方法是有返回值的。
这里总结一下Callable和Runnable的区别:
Runnable:实际执行的是 run 方法,没有返回值
Callable: 实际执行的是 call 方法,有返回值
下面我们来看下怎么用:
新建一个类,实现Callable接口,可以指定返回值的类型,并实现call方法。
class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(1000);
return "success";
}
}
看Thread源码可以看到,Thread构造接收的是Runnable类型的参数
所以,我们不能直接将Callable的实现类直接传进去 , 需要用到 FutureTask 包装一下
先来看下 FutureTask 的代码,可以看到 FutureTask 类实现了RunnableFuture接口
RunnableFuture 又继承了 Runnable 接口,所以,本质上还是属于实现Runnable接口的方式
这样一来,我们就可以将FutureTask 类型的对象传给Thread了。
用法如下:
public static void main(String[] args) {
/*创建 Callable 对象*/
MyCallable callable = new MyCallable();
/*包装成FutureTask*/
FutureTask<String> stringFutureTask = new FutureTask<>(callable);
/*创建线程并开始执行*/
new Thread(stringFutureTask).start();
System.out.println("线程开始执行");
try {
/*拿返回结果*/
String result = stringFutureTask.get();
System.out.println("执行完毕 拿到结果");
System.out.println("result = " + result);
} catch (Exception e) {
e.printStackTrace();
} finally {
}
System.out.println("主线程执行");
}
下面来看下运行结果:
可以看到,我们可以拿到执行结果了。需要注意的是,这里调FutureTask的get会阻塞住当前线程
java 简化写法:
public static void main(String[] args) {
/*创建FutureTask 对象*/
FutureTask<String> stringFutureTask = new FutureTask<>(() -> {
Thread.sleep(1000);
return "success";
});
/*创建线程并开始执行*/
new Thread(stringFutureTask).start();
System.out.println("线程开始执行");
try {
/*拿返回结果*/
String result = stringFutureTask.get();
System.out.println("执行完毕 拿到结果");
System.out.println("result = " + result);
} catch (Exception e) {
e.printStackTrace();
} finally {
}
System.out.println("主线程执行");
}
kotlin写法就更简单了,如下:
fun main() {
/*创建FutureTask对象*/
val futureTask = FutureTask {
Thread.sleep(1000)
"Success"
}
/*创建线程执行任务*/
Thread(futureTask).start()
/*打印*/
println("futureTask = ${futureTask.get()}")
}
好了,本篇文章就是这样
下一篇:
如果你觉得本文对你有帮助,麻烦动动手指顶一下,可以帮助到更多的开发者,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客,谢谢!
以上是关于线程的基本使用的主要内容,如果未能解决你的问题,请参考以下文章
html PHP代码片段: - AJAX基本示例:此代码演示了使用PHP和JavaScript实现的基本AJAX功能。
JUC并发编程 共享模式之工具 JUC CountdownLatch(倒计时锁) -- CountdownLatch应用(等待多个线程准备完毕( 可以覆盖上次的打印内)等待多个远程调用结束)(代码片段