Thread
class MyThrad extends Thread { // 线程的主体类
private String title;
public MyThrad(String title) {
this.title = title;
}
@Override
public void run() { // 线程的主体方法
for (int i = 0; i < 10; i++) {
System.out.println("i:" + i + ",title:" + this.title);
}
}
}
public class JavaDemo {
public static void main(String[] args) {
new MyThrad("线程1").start();
new MyThrad("线程2").start();
new MyThrad("线程3").start();
}
}
在java文件中调用start, java中使用JNI技术调用start0, jvm根据不同系统调用不同系统底层实现的函数, 实现资源分配
Runnable
class runnableImpl implements Runnable { // 线程的主体类
private String title;
public runnableImpl(String title) {
this.title = title;
}
@Override
public void run() { // 线程的主题方法
for (int i = 0; i < 10; i++) {
System.out.println("i:" + i + ",title:" + this.title);
}
}
}
public class JavaDemo {
public static void main(String[] args) {
// Thread
// new MyThrad("线程1").start();
// new MyThrad("线程2").start();
// new MyThrad("线程3").start();
// Runnable
Thread threadA = new Thread(new runnableImpl("线程1"));
Thread threadB = new Thread(new runnableImpl("线程2"));
Thread threadC = new Thread(new runnableImpl("线程3"));
threadA.start();
threadB.start();
threadC.start();
}
}
Runnbale lambada
class runnableImpl implements Runnable { // 线程的主体类
private String title;
public runnableImpl(String title) {
this.title = title;
}
@Override
public void run() { // 线程的主题方法
for (int i = 0; i < 10; i++) {
System.out.println("i:" + i + ",title:" + this.title);
}
}
}
public class JavaDemo {
public static void main(String[] args) {
// Thread
// new MyThrad("线程1").start();
// new MyThrad("线程2").start();
// new MyThrad("线程3").start();
// Runnable
// Thread threadA = new Thread(new runnableImpl("线程1"));
// Thread threadB = new Thread(new runnableImpl("线程2"));
// Thread threadC = new Thread(new runnableImpl("线程3"));
// threadA.start();
// threadB.start();
// threadC.start();
// Runnable lambada
for (int i = 0; i < 3; i++) {
String title = "线程对象" + i;
Runnable run = () -> {
for (int j = 0; j < 10; j++) {
System.out.println(title + "运行, j=" + j);
}
};
new Thread(run).start();
}
}
}
Thread和Runnable的关系
打开Thread类的定义
public class Thread extends Object implements Runnable {}
发现现在Thread类也是Runnable接口的子类, 那么之前继承Thread类, 其实也是覆写的Runnbale
类
- 多线程的设计之中, 使用了代理设计模式的结构, 用户自定义的线程主体只是负责项目核心功能的实现, 而所有的辅助实现全部交给
Thread
类来处理. - 在进行
Thread
启动多线程的时候, 调用的是start()
方法, 而后找到的是run()
方法, 当通过Thread
类传递了一个Runnable
接口对象的时候, 那么该接口对象将被Thread
类中的target
属性所保存, 在start()
方法执行的时候, 会调用Thread
类中的run()
方法, 而这个run()
方法会去调用Runnable
接口子类被覆写过的run()方法.
多线程开发本质: 多个线程可以进行同一个资源的抢占
Callable实现多线程
从最传统的开发来讲, 如果进行多线程的实现, 肯定依靠Runnable
, 但是Runnable
接口有一个问题, 线程执行完毕以后无法获取一个返回值, 所以在JDK1.5以后提出了一个新的线程实现接口, java.util.concurrent.Callable
接口.
接口的定义
@FunctionalInterface
public interface Callable<V> {
public V call() throws Exception;
}
可以发现Callable
定义的时候可以设置一个泛型, 此泛型的类型就是返回值的类型, 这样的好处, 可以避免向下转型带来的安全隐患.
Callable
与Thread
的关系
代码示例
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
class MyThread implements Callable<String> {
@Override
public String call() throws Exception {
for (int i = 0; i < 10; i++) {
System.out.println("**********线程执行, i=" + i);
}
return "线程执行完毕";
}
}
public class CallableDemo {
public static void main(String[] args) throws Exception {
FutureTask<String> task = new FutureTask<>(new MyThread());
new Thread(task).start();
System.out.println("线程返回数据," + task.get());
}
}
output
**********线程执行, i=0
**********线程执行, i=1
**********线程执行, i=2
**********线程执行, i=3
**********线程执行, i=4
**********线程执行, i=5
**********线程执行, i=6
**********线程执行, i=7
**********线程执行, i=8
**********线程执行, i=9
线程返回数据,线程执行完毕
Runnable
与Callable
的区别
-
Runnable
是在JDK1.0提出的多线程实现接口, 而Callable
是在JDK1.5之后提出的 -
java.lang.Runnable
接口之中只提供有一个run()
方法, 并且没有返回值; -
java.util.concurrent.Callable
接口提供有一个call()
方法, 可以有返回值
只要想使用多线程, 必须使用Thread中的start()
多线程运行状态
对于多线程编写程序的流程: 定义线程主题类, 而后通过Thread
类进行线程的启动, 但是并不意味着你调用了start()
方法, 线程就已经开始运行了, 因为整体的线程处理有自己的一套运行的状态
- 任何线程对象都应该使用
Thread
类进行封装, 所以线程的启动使用的是start()
, 但是启动的时候若干个线程都进入到一种就绪状态, 现在并没有开始执行 - 进入到就绪状态以后就需要等到进行资源调度, 当某一个线程调度成功以后则进入到运行状态(run()方法), 但是所有的线程不可以一直处于运行状态, 中间需要产生一些暂停的状态, 例如: 某个线程执行一段时间以后就需要让出资源, 而后这个线程就会进入到阻塞状态, 随后重新回归到就绪状态.
- 当
run()
方法执行完毕以后, 实际上该线程的主要任务也就结束了, 那么此时就可以直接进入到停止状态