参考项目:https://github.com/wodongx123/ThreadDemo
public class ExtendsThread extends Thread {
//不设置初始值就是 i=0了
private int i;
public void run(){
for(;i<100 ; i++){
//在Thread类中,getName就能获取当前线程的线程名
System.out.println(getName() + " " + i);
}
}
public static void main(String[] args) {
//这么写报错了java.lang.IllegalThreadStateException
//Thread.currentThread().start();
for(int i=0; i<100; i++){
//由于main函数是静态函数,不能直接getName,要用Thread的静态方法
System.out.println(Thread.currentThread().getName() + " " + i);
if(i == 20){
new ExtendsThread().start();
new ExtendsThread().start();
}
}
}
}
public class RunnableThread implements Runnable {
private int i;
public void run() {
// 引入Runnable必须要加入的方法
for(;i<100 ; i++){
//Runnable方法的话就没有getName了,所以还是用Thread的静态方法获取名字
System.out.println(Thread.currentThread().getName()+ " " + i);
}
}
public static void main(String[] args) {
//这么写报错了java.lang.IllegalThreadStateException
//Thread.currentThread().start();
for(int i=0; i<100; i++){
//由于main函数是静态函数,不能直接getName,要用Thread的静态方法获取thread实例
System.out.println(Thread.currentThread().getName() + " " + i);
if(i == 20){
RunnableThread st = new RunnableThread();
new Thread(st, "线程1").start();
new Thread(st, "线程2").start();
}
}
}
}
public class CallableThread implements Callable<Integer>{
//这个call方法就差不多是Runnable的run方法了,允许抛出异常,有返回值
public Integer call() throws Exception {
int i=0;
for(; i<100; i++){
System.out.println(Thread.currentThread().getName() + " " + i);
}
return i;
}
public static void main(String[] args){
//实例化Callable对象
CallableThread callableThread = new CallableThread();
//使用FutureTask来包装对象
FutureTask<Integer> task = new FutureTask<Integer>(callableThread);
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 20) {
//实际上就是启动了一个Callable线程
new Thread(task, "Callable线程").start();
}
}
try {
//获取返回值,Callable的返回值是有可能抛出异常的,所以要try/catch
System.out.println("Callable返回值:" + task.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}
我们一般都使用实现Runnable接口、Callable接口的方式来创建新线程。
\ | Thread | Runnable | Callable |
实现方法 | extends | implements | |
可继承其他类 | 否 | 是 | |
线程内资源共享 | 否 | 是 | |
返回值,抛出异常 | 否 | 是 |
一种专门在后台运行的线程,它的任务就是给其他线程提供服务。
在新建一个线程之后,一定要调用start()方法才能启动线程,系统会把run()方法当成线程执行体来执行。如果调用线程的run()方法,就会把线程类当成普通对象来处理了,run()方法会变成普通的方法,而不是线程执行体。
简单来说,就是线程实际上是一个一次性用品,不像普通的类一样可以再次使用,在走完Thread的生命周期后,就不能再次使用了,想要再用就得再次new一个实例出来。如果对不是处于新建状态的线程调用start()方法,就会报java.lang.IllegalThreadStateException。
在源码的start()中,会对threadStatus这个变量做判断,如果不等于0就会报java.lang.IllegalThreadStateException。而这个变量正是代表Thread的状态,这个值会在新建的时候正好为0。
private volatile int threadStatus;
......
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
.......
}
对于Thread类的run方法而言,其实就是判断target是否为空,非空就运行而已。
而这个target就是实现Runnable接口的类。
public class Thread implements Runnable {
/* What will be run. */
private Runnable target;
......
@Override
public void run() {
if (target != null) {
target.run();
}
}
}
Java中的多线程你只要看这一篇就够了
https://www.cnblogs.com/wxd0108/p/5479442.html
锁和监视器的区别
https://www.cnblogs.com/keeplearnning/p/7020287.html#4181397
疯狂JAVA讲义(第5版)
p733 - p779