Java多线程
1.多线程
实现方法:
一、继承Thread,重写run方法,调用start即可。
Class Thread1 extends Thread{
Public void run(){
//添加代码
}
}
Public static void main(String[] args){
Thread1 st = new Thread1();
St.start();
}
二、实现runnable接口,重写run方法,调用start。
Class RunThrad implements runnable{
Public void run(){
//添加代码
}
}
RunThread t = new RunThread();
Thread th = new Thread(t);
th.start();
三、实现Callable接口类,并重写call方法,使用FutureTask类来包装Callable实现类的对象,并且使用FutureTask对象来作为Thread对象的target来创建线程。
class Mycallable implements Callable<Integer>{
Public int call(){
//添加代码
}
}
public static void main(String[] args){
Mycallable<Integer> mycall = new Mycallable<Integer>();
FutureTask<Integer> ft = new FutureTask<Integer>(mycall);
Thread th = new Thread(ft);
th.start();
}
实现runnable和callable比继承Thread方法的优势:
1、避免单继承的问题。
2、线程池只能够放入runnable和callable类的线程。
线程主要有五种状态,如下:
接下来介绍sleep,wait,notify,notifyAll,join,yield六种方法
对于wait,notify,notifyAll这三个,属于object类的方法,但必须搭配synchronized同步块来使用,即在synchronized修饰的同步代码块中或者方法中调用wait或者notify/notifyAll:
由于wait,notify/notifyAll是放在同步代码块中的,所以线程在执行的时候,肯定是进入了临界状态的,即该线程肯定是获得了锁的。
当执行wait方法时,会把当前的锁释放掉,让出cpu,进入等待状态。
当执行notify/notifyAll方法时,唤醒一个等待该对象锁的线程,然后继续往下执行,直到执行完synchronized的代码后,再将锁释放。(注意,notify/notifyAll执行后,并不立即释放锁,而是需要等待执行完synchronized的代码后)
如果在线程A,线程B中,在线程A中,执行wait,在线程B中执行notify,如果线程B先执行了notify,然后就结束了,然后线程A才去执行wait,那么此时线程A就无法被唤醒了。举例如下:有3个线程A,B,C。
class T implements Runnable{
public String i;
public String index;
public T(String i,String index){
this.i = i;
this.index = index;
}
@Override
public void run() {
synchronized (index) {
while (true) {
try {
index.notifyAll();
System.out.println(i);
index.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class demo {
public static void main(String[] args){
String string1 = "s1";
String string2 = "s2";
String string3 = "s3";
String index = "test";
T a1 = new T(string1,index);
T a2 = new T(string2,index);
T a3 = new T(string3,index);
Thread thread1 = new Thread(a1);
Thread thread2 = new Thread(a2);
Thread thread3 = new Thread(a3);
thread1.start();
thread2.start();
thread3.start();
}
}
输出结果:
s2
s1
s3
s1
s2
s1
s3
s1
……
……
结果思考:线程不会停止。当三个线程并行启动时,s2最先抢到,进入同步代码块,这时候唤醒其他线程进行等待就绪,执行到wait方法,进入阻塞,并释放掉锁。这时候s1进入cpu,进入同步代码块,唤醒其他行程等待就绪,并执行到wait方法,并释放掉锁。进入线程循环……线程不会停止。
如果将notify方法注释掉,执行结果为
s1
s3
s2
结果思考:线程1进入同步代码块时,执行到wait方法,进入阻塞状态,无法被唤醒。线程2启动并进入阻塞,线程2启动并进入阻塞。