A、Java中实现多线程的方式有两种:继承Thread类,实现Runnable接口。
class Thread1 extend Thread{
public void run(){
}
}
class Runnable1 implements Runnable{
public void run(){
}
}
其实Thread也是实现Runnable接口的:
class Thread implements Runnable {
//…
public void run() {
if (target != null) {
target.run();
}
}
}
两个孰优孰劣总结一下吧:
实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。
B、线程强制执行
package com.tmt.test_code.thread;
class JoinThread implements Runnable {
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName());
}
}
public static void main(String[] args) {
JoinThread he = new JoinThread();
Thread demo = new Thread(he,"线程");
demo.start();
for(int i=0;i<10;++i){
if(i>5){
try{
demo.join(); //强制执行demo
}catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("main 线程执行-->"+i);
}
}
}
执行结果:
线程
main 线程执行-->0
main 线程执行-->1
main 线程执行-->2
main 线程执行-->3
main 线程执行-->4
main 线程执行-->5
线程
线程
main 线程执行-->6
main 线程执行-->7
main 线程执行-->8
main 线程执行-->9
说明在执行到大于5时,如果demo对应的线程还未执行完毕,则必须等它执行完毕后才能继续执行下面的程序。
C、sleep()和wait()的区别
package com.tmt.test_code.thread;
public class DeadLockThread implements Runnable{
/**
* 一个简单的死锁类及显示sleep()和wait()的区别
* @author iStar
* 当类的对象field_1=1时(T1),先锁定lock_1,睡眠1000毫秒,然后锁定lock_2;
* 而T1在睡眠的时候另一个flag=2的对象(T2)线程启动,先锁定lock_2,睡眠1000毫秒,等待T1释放lock_1;
* T1睡眠结束后需要锁定lock_2才能继续执行,而此时lock_2已被T2锁定;
* T2睡眠结束后需要锁定lock_1才能继续执行,而此时lock_1已被T1锁定;
* T1、T2相互等待,都需要对方锁定的资源才能继续执行,从而死锁。
*/
int field_1 = 1;
static Object lock_1 = new int[1];
static Object lock_2 = new int[1];
public void run(){
if(field_1 == 1){
synchronized (lock_1) {
try {
// lock_1.wait(1000);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock_2) {
System.out.println("method1");
}
}
}
if(field_1 == 2){
synchronized (lock_2) {
try {
// lock_2.wait(1000);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock_1) {
System.out.println("method2");
}
}
}
}
public static void main(String [] arg){
DeadLockThread deadLockThread1 = new DeadLockThread();
DeadLockThread deadLockThread2 = new DeadLockThread();
deadLockThread1.field_1 = 1;
deadLockThread2.field_1 = 2;
Thread thread1 = new Thread(deadLockThread1);
Thread thread2 = new Thread(deadLockThread2);
thread1.start();
thread2.start();
}
}
当使用Thread.sleep(1000)时,打印不出任何东西。当注释掉Thread.sleep(1000),使用wait()时可以打印出method1 method2
说明:
1、在调用sleep()方法的过程中,线程不会释放对象锁。
2、在调用wait()方法的过程中,线程会释放对象锁,进入等待此对象的等待锁定池。只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
下面的例子也可以看出来
package com.tmt.test_code.thread;
/**
* java中的sleep()和wait()的区别
*
* @author Hongten
* @date 2013-12-10
*/
public class SleepWaitDeffirent {
static Object object = new Object();
public static void main(String[] args) {
new Thread(new Thread1()).start();
try {
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
new Thread(new Thread2()).start();
}
private static class Thread1 implements Runnable {
@Override
public void run() {
synchronized (object) {
System.out.println("enter thread1...");
System.out.println("thread1 is waiting...");
try {
// 调用wait()方法,线程会放弃对象锁,进入等待此对象的等待锁定池
object.wait();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("thread1 is going on ....");
System.out.println("thread1 is over!!!");
}
}
}
private static class Thread2 implements Runnable {
@Override
public void run() {
synchronized (object) {
System.out.println("enter thread2....");
System.out.println("thread2 is sleep....");
// 只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
object.notifyAll();
// ==================
// 区别
// 如果我们把代码:TestD.class.notify();给注释掉,即TestD.class调用了wait()方法,但是没有调用notify()
// 方法,则线程永远处于挂起状态。
try {
// sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,
// 但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
// 在调用sleep()方法的过程中,线程不会释放对象锁。
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("thread2 is going on....");
System.out.println("thread2 is over!!!");
}
}
}
}