Thread 用法
public class MyThread extends Thread{
private String name;
public MyThread(String name) {
this.name = name;
}
public void run(){
for (int i = 0; i < 5; i++) {
try {
System.out.println("--------------"+i+"-----"+this.name);
sleep((int) Math.random() * 10);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class TestThread {
public static void main(String[] args) {
MyThread myThread1 = new MyThread("123");
MyThread myThread2 = new MyThread("456");
myThread1.start();
myThread2.start();
/*MyRunnable myRunnable1 = new MyRunnable("123");
MyRunnable myRunnable2 = new MyRunnable("456");
new Thread(myRunnable1).start();
new Thread(myRunnable2).start();*/
}
}
注意: 调用start() 方法之后 程序不会马上执行,线程的状态变为可运行状态(Runnable),什么时候运行取决于系统
多线程的执行结果是乱序的,每次执行的顺序多是随机的
但是 start() 方法重复调用的话 ,会抛出异常, java.lang.IllegalThreadStateException
MyThread myThread1 = new MyThread("123");
MyThread myThread2 = myThread1;
myThread1.start();
myThread2.start();
原因是 Thread 有一个判断
private volatile int threadStatus = 0;
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
主要原因是 myThread1 中的 threadStatus 对于 myThread2 是共享的(因为 volatile)
在JM 中每个状态都会去判断 threadStatus 的值,因为 threadStatus 在1中初始化为 0 ,所以在2中每次执行都会报错。
Thread 是 继承 Runable
public class Thread implements Runnable
Runnable
public class MyRunnable implements Runnable {
private String name;
public MyRunnable(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
System.out.println("--------------"+i+"-----"+this.name);
Thread.sleep((int) Math.random() * 10);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class TestThread {
public static void main(String[] args) {
/*MyThread myThread1 = new MyThread("123");
MyThread myThread2 = new MyThread("456");
myThread1.start();
myThread2.start();*/
MyRunnable myRunnable1 = new MyRunnable("123");
MyRunnable myRunnable2 = new MyRunnable("456");
new Thread(myRunnable1).start();
new Thread(myRunnable2).start();
}
}
为什么要这样才能执行那?
先看Runnable 接口 ,注意我这里说的是接口
代码:
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
注释很简单 ,当你用Runnable创建一个线程的时候,必须实现 run()方法。
而在Thread 中
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
Thread(Runnable target, AccessControlContext acc) {
init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
}
init 是Thread的初始化方法,在这里 就是 为什么 要去 new Thread(myRunnable1).start(); 这样启动一个线程。
Thread 和Runnable 的区别
总结: Thread是一个类,只能单继承,但是Runnable是接口,可以多继承,适合资源共享,增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类
mian方法也是一个线程,java程序中每次执行至少会开启2个线程,一个是main线程,一个是垃圾回收线程