run()和start()
这是多线程最常用的方法了,把需要并行处理的代码放在run()中,run方法必须是public权限,返回值为void。start()方法启动线程自动调用run()方法
public class Case3 {
private static class A extends Thread{
@Override
public void run(){
System.out.println("我是A");
}
}
private static class B extends Thread{
@Override
public void run(){
System.out.println("我是B");
}
}
public static void main(String[] args) {
A a=new A();
B b=new B();//把a b放入就绪队列中
b.setPriority(Thread.MAX_PRIORITY);//设置优先级(也不一定百分百在前面)
a.start();
b.start();
System.out.println("我是主线程");
}
}
sleep()和interrupt()
sleep:睡眠指定时间,睡眠期间让出cpu的执行权,但睡眠时间一到就会立即执行,注意该方法要捕获异常。如果未到时间就需要使用interrupt()来随时唤醒,会抛出interrupt()异常。
public class test {
public static void main(String[] args) throws Exception {
Thread thread0 = new Thread(()-> {
try {
System.out.println( "\t" + Thread.currentThread().getName() + "\t太困了,让我睡10秒,中间有事叫我,zZZ。。。");
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("\t" + Thread.currentThread().getName() + "\t被叫醒了,又要继续干活了");
}
});
thread0.start();
// 这里睡眠只是为了保证先让上面的那个线程先执行
Thread.sleep(2000);
new Thread(()-> {
System.out.println( "\t" + Thread.currentThread().getName() + "\t醒醒,醒醒,别睡了,起来干活了!!!");
// 无需获取锁就可以调用interrupt
thread0.interrupt();
}).start();
}
}
join()
join()方法使调用该方法的线程在此之前执行完毕,也就是等待调用该方法的线程执行完毕后再往下继续执行。注意该方法也要捕获异常。
public static void main(String[] args) throws InterruptedException {
Thread a=new MyThread();//创建一个线程对象,该线程要干的工作就在该线程类中,已被覆写
a.start();//把a线程放入就绪队列
a.join();//1.主线程放弃CPU,2,直到a结束之前,承诺再也不抢cpu,
//主线程会阻塞在这里,直到a执行结束,才接着往下执行
Runnable target=new MyRunnable();//创建一个目标对象,具体要做的实现,在run方法
Thread b=new Thread(target);//拿着目标对象,去创建线程对象,线程要干的活就是目标对象指定的
b.start();
b.join();
yield()
它与sleep()类似,只是不能由用户指定暂停多长时间,并且yield()方法只能让同优先级的线程有执行的机会,它是一个好人那种,当cpu轮到它了,他说不急,先让别的线程执行吧
public static void main(String[] args) {
new Thread(new Runnable() {
int sum = 0;
@Override
public void run() {
long beginTime=System.currentTimeMillis();
for (int i = 0; i < 99999; i++) {
sum += 1;
// 去掉该行执行用2毫秒,加上271毫秒
Thread.yield();
}
long endTime=System.currentTimeMillis();
System.out.println("用时:"+ (endTime - beginTime) + " 毫秒!");
}
}).start();
}
wait() notify() notifyAll()
wait、notify和notifyAll方法不能被子类重写,Object类是所有类的超类,因此在程序中可以通过this或者super来调用this.wait(), super.wait()。
用途·:这三个方法用于协调多个线程对共享数据的存取,所以必须在Synchronized语句块内使用这三个方法。前面说过Synchronized这个关键字用于保护共享数据,阻止其他线程对共享数据的存取。但是这样程序的流程就很不灵活了,如何才能在当前线程还没退出Synchronized数据块时让其他线程也有机会访问共享数据呢?此时就用这三个方法来灵活控制。
wait(): 导致线程进入等待阻塞状态,会一直等待直到它被其他线程通过notify()或者notifyAll唤醒。该方法只能在同步方法中调用。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。
notify(): 该方法只能在同步方法或同步块内部调用, 随机选择一个(注意:只会通知一个)在该对象上调用wait方法的线程,解除其阻塞状态
notifyAll(): 唤醒所有的wait对象notifyAl()则从对象等待池中移走所有等待那个对象的线程并放到锁标志等待池中。
注意:
Object.wait()和Object.notify()和Object.notifyall()必须写在synchronized方法内部或者synchronized块内部让哪个对象等待wait就去通知notify哪个对象,不要让A对象等待,结果却去通知B对象,要操作同一个对象