参考:
导航:
比较
实现接口的方式比继承类的方式更灵活,
也能减少程序之间的耦合度,面向接口编程也是设计模式6大原则的核心
implements Runnable
public class RunnalbleTest2 implements Runnable {
private int threadCnt = 10;
@Override
public void run() {
while (true) {
if (threadCnt > 0) {
System.out.println(Thread.currentThread().getName() +
" 剩余个数 " + threadCnt);
threadCnt--;
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
break;
}
}
}
public static void main(String[] args) {
RunnalbleTest2 runnalbleTest2 = new RunnalbleTest2();
new Thread(runnalbleTest2).start();
new Thread(runnalbleTest2).start();
new Thread(runnalbleTest2).start();
new Thread(runnalbleTest2).start();
}
}
//Thread-1 剩余个数 10
//Thread-2 剩余个数 9
//Thread-0 剩余个数 8
//Thread-3 剩余个数 7
//Thread-1 剩余个数 6
//Thread-0 剩余个数 5
//Thread-2 剩余个数 4
//Thread-3 剩余个数 3
//Thread-1 剩余个数 2
//Thread-0 剩余个数 1
可以看出该实例中虽然是2个线程,但操作的threadCnt却是一个,实现了资源共享。
extends Thread
public class ThreadTest2 extends Thread {
private int threadCnt = 10;
@Override
public void run() {
while (true) {
if (threadCnt > 0) {
System.out.println(Thread.currentThread().getName() +
" 剩余个数 " + threadCnt);
threadCnt--;
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
break;
}
}
}
public static void main(String[] args) {
new ThreadTest2().start();
new ThreadTest2().start();
}
}
//Thread-0 剩余个数 10
//Thread-1 剩余个数 10
//Thread-0 剩余个数 9
//Thread-1 剩余个数 9
//Thread-0 剩余个数 8
//Thread-1 剩余个数 8
//Thread-0 剩余个数 7
//Thread-1 剩余个数 7
//Thread-0 剩余个数 6
//Thread-1 剩余个数 6
//Thread-0 剩余个数 5
//Thread-1 剩余个数 5
//Thread-0 剩余个数 4
//Thread-0 剩余个数 3
//Thread-1 剩余个数 4
//Thread-0 剩余个数 2
//Thread-1 剩余个数 3
//Thread-0 剩余个数 1
//Thread-1 剩余个数 2
//Thread-1 剩余个数 1
start()方法和run()方法区别
import java.text.SimpleDateFormat;
public class TestNoStart {
static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.sss");
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread() {
@Override
public void run() {
pong(1);
try {
Thread.sleep(7000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t2 = new Thread() {
@Override
public void run() {
pong(2);
try {
Thread.sleep(7000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t1.start();
t2.start();
// t1.run();
// t2.run();
System.out.println(getTime() + " ping~~~~");
}
static void pong(int i) {
System.out.println(getTime() + " pong~" + i);
}
static String getTime() {
return dateFormat.format(System.currentTimeMillis());
}
}
//run
//2019-10-31 11:15:49.049 pong~1
//2019-10-31 11:15:56.056 pong~2
//2019-10-31 11:16:03.003 ping~~~~
//start
//2019-10-31 11:16:27.027 ping~~~~
//2019-10-31 11:16:27.027 pong~2
//2019-10-31 11:16:27.027 pong~1
start()方法和run()方法区别:
涉及到线程的几个状态
新建状态:使用 new 关键字和 Thread 类(或其子类)建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
就绪状态:当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
运行状态:如果就绪状态的线程获取到 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
只有调用了start()方法,才会表现出多线程的特性,
不同线程的run()方法里面的代码交替执行。
如果只是调用run()方法,那么代码还是同步执行的,必须等待一个线程的run()方法里面的代码全部执行完毕之后,
另外一个线程才可以执行其run()方法里面的代码。