常见的两种线程建立方式:继承Thread类和实现Runnable接口
具体例子:这里说明一点比较常用继承来实现接口,以为比较简单化。
package test;
import org.junit.Test;
public class TestThread {
@Test
public void testForeach() throws InterruptedException {
Mythread mythread1 = new Mythread();
Mythread mythread2 = new Mythread();
mythread1.start();
mythread2.start();
MyThread1 myThread13 = new MyThread1();
Thread thread1 = new Thread(myThread13);
Thread.sleep(100);
thread1.start();
try {
Thread thread = new Thread(new MyThread1());
Thread.sleep(1000);
thread.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//1,继承(extendsThread)
class Mythread extends Thread {
int j = 3;
{
for (int i = 0; i < 3; i++){
System.out.println("当前线程名:" + Thread.currentThread() + ";" + j--);
}
}
}
//实现(implements Runnable)
class MyThread1 implements Runnable {
@Override
public void run() {
int j = 4;
for (int i = 0; i < 4; i++){
System.out.println("当前线程名:" + Thread.currentThread() + ";" + j--);
}
}
}
结果输出:
当前线程名:Thread[main,5,main];3
当前线程名:Thread[main,5,main];2
当前线程名:Thread[main,5,main];1
当前线程名:Thread[main,5,main];3
当前线程名:Thread[main,5,main];2
当前线程名:Thread[main,5,main];1
当前线程名:Thread[Thread-2,5,main];4
当前线程名:Thread[Thread-2,5,main];3
当前线程名:Thread[Thread-2,5,main];2
当前线程名:Thread[Thread-2,5,main];1
当前线程名:Thread[Thread-3,5,main];4
当前线程名:Thread[Thread-3,5,main];3
当前线程名:Thread[Thread-3,5,main];2
当前线程名:Thread[Thread-3,5,main];1
上面的例子如果你放开try…catch,并去掉线程沉睡,这将会体现出多线程的不安全性。
多次的运行结果会不同,比如:很显然少了一个“4”
当前线程名:Thread[main,5,main];3
当前线程名:Thread[main,5,main];2
当前线程名:Thread[main,5,main];1
当前线程名:Thread[main,5,main];3
当前线程名:Thread[main,5,main];2
当前线程名:Thread[main,5,main];1
当前线程名:Thread[Thread-2,5,main];4
当前线程名:Thread[Thread-2,5,main];3
当前线程名:Thread[Thread-2,5,main];2
当前线程名:Thread[Thread-3,5,main];4
当前线程名:Thread[Thread-2,5,main];1
当前线程名:Thread[Thread-3,5,main];3
当前线程名:Thread[Thread-3,5,main];2
当前线程名:Thread[Thread-3,5,main];1