java多线程 不用thread_java多线程-Thread

大纲

sleep

yield

join

setDaemon

sleep:

public static native void sleep(long millis) throws InterruptedException;

sleep是本地静态方法。

sleep的作用是让线程进入TIME_WAITING状态,参数是多少毫秒。

classTest {

public static voidmain(String[] args){

Thread thread = new Thread(()->{

try{

Thread.sleep(2000);

System.out.println("over");

} catch(InterruptedException e) {

System.out.println("interrupt");

}

});

thread.start();

}

}

/**

结果:2秒后看到over

*/

sleep可被interrupt打断,抛出InterruptedException。

classTest {

public static voidmain(String[] args){

Thread thread = new Thread(()->{

try{

Thread.sleep(2000);

System.out.println("over");

} catch(InterruptedException e) {

System.out.println("interrupt");

}

});

thread.start();

thread.interrupt();

}

}

/**

结果:立刻看到interrupt

*/

注意:sleep方法并不释放锁。

yield:

public static native void yield();

yield是一个本地静态方法。

yield表示当前线程申请交出执行权,但并不是一定会交出,依赖于系统的线程调度。

因此该方法并不稳定。

classTest {

public static void main(String[] args) throwsInterruptedException {

TestYield t0 = new TestYield("thread0");

TestYield t1 = new TestYield("thread1");

t0.start();

t1.start();

}

}

class TestYield extendsThread {

publicTestYield(String name) {

super(name);

}

@Override

public voidrun() {

for (int i = 0; i < 10; i++) {

if (Thread.currentThread().getName().equals("thread0")&&i==5) {

yield();

}

System.out.println(Thread.currentThread().getName() + ":" +i);

}

}

}

/**

结果:t0打印4后会交出执行权,一般不会连续打印thread0:4 thread0:5

*/

注意:yield 方法放弃执行权但并不释放锁。

join:

之前看了一些博客说join就是把多线程变成单线程,其实并不是,执行join还是多线程。

classTest {

public static void main(String[] args) throwsInterruptedException {

TestJoin t0 = newTestJoin();

TestJoin t1 = newTestJoin();

t0.start();

t1.start();

t0.join();

for(int i=0;i<100;i++){

System.out.println(Thread.currentThread().getName() + ":" +i);

}

}

}

class TestJoin extendsThread{

@Override

public voidrun(){

for(int i=0;i<100;i++){

System.out.println(Thread.currentThread().getName() + ":" +i);

}

}

}

/**

结果:t0.t1线程交替打印至t0执行结束,然后开始t1,main线程交替打印。

*/

结合源码看看join做了什么。

public final void join() throwsInterruptedException {

join(0);

}

public final synchronized void join(longmillis)

throwsInterruptedException {

long base =System.currentTimeMillis();

long now = 0;

if (millis < 0) {

throw new IllegalArgumentException("timeout value is negative");

}

if (millis == 0) {

while(isAlive()) {

wait(0);

}

} else{

while(isAlive()) {

long delay = millis -now;

if (delay <= 0) {

break;

}

wait(delay);

now = System.currentTimeMillis() -base;

}

}

}

执行过程(这里讨论执行无参join方法,如果执行有参数join(xx),其实就是让main线程wait(xx)):

main线程执行t0.join()。

main线程执行join(),join()执行join(0),join(long millis)是一个同步方法。

while(isAlive)这里的isAlive是t0的isAlive,如果t0存活,此时main线程持有t0的对象锁,执行wait。 (while确保了其他线程持有t0锁执行notifyAll后也无法唤醒main线程)

main线程进入WAITING状态。

t0,t1状态正常,交替执行至t0结束。

t0结束后,由本地方法执行t0.notifyAll,main线程被唤醒。(源码中并看不到如何notifyAll的,线程结束后会执行一个本地方法notifyAll)

这时如果t1还没执行完成,main和t1交替执行。

https://blog.csdn.net/erica_1230/article/details/69388742 中介绍了:线程结束时调用的本地方法notifyAll

static void ensure_join(JavaThread*thread) {

Handle threadObj(thread, thread->threadObj());

assert(threadObj.not_null(), "Java thread object must exist");

ObjectLocker lock(threadObj, thread);

thread->clear_pending_exception();

java_lang_Thread::set_stillborn(threadObj());

java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED);

java_lang_Thread::set_thread(threadObj(), NULL);

lock.notify_all(thread);

thread->clear_pending_exception();

}

结论:当一个线程a执行线程b.join()则,线程a等待至线程b执行完毕后继续执行,这个过程并不影响其线程的执行。

setDaemon

private boolean daemon = false;

public final void setDaemon(booleanon) {

checkAccess();if(isAlive()) {throw newIllegalThreadStateException();

}

daemon=on;

}

线程的类型分为用户线程与守护线程,我们平时使用的一般是用户线程。

调用setDaemon(true)方法即可将线程设置问守护线程。注意isAlive方法判断该线程状态,因此setDaemon必须在线程start之前。

两者区别:用户线程运行结束,只剩下守护线程工作时虚拟机就会退出。所以说守护线程随时可能中断,而且随着用户线程消失而消失。

守护线程中创建的线程依然是守护线程。(源码中判断parent.isDaemon并把结果赋值给子线程)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值