多线程--java


多线程

java每创建一个Thread就创建一个线程,java创建的线程默认是处于非阻塞状态,异步,以及线程内存共享,

阻塞非阻塞是程序等待调用结果的状态

阻塞调用: 没立即得到结果,当前线程会被挂起 ,也就是处于阻塞状态

非阻塞调用:没立即得到结果,不会阻塞当前线程

同步异步是消息通信机制

同步: 等阻塞调用得到返回结果后,才返回I/O系统

异步:因为不阻塞当前线程,立即返回I/O系统,CPU可以去处理其它线程,等收到返回结果后,再去处理该线程

默认都是非阻塞调用,异步通信机制,因为它可以大大提高CPU性能。

为了更高效地减小线程的开销,多个线程可以对同一个内存资源共享调用,但会造成线程不安全

线程不安全:(多线程和单线程运行的结果不一样)

解释: 多线程调用与单线程(加锁)调用相同内存资源的结果不一样

 线程安全:(每次运行的结果和单线程运行的结果是不一样的,而且其他的变量的值也和预期的是一样的)

加锁,通过加synchronized ,使某程序不能内存共享,阻塞调用,异步通信机制,所以对相同内存只能单线程运行。

注意:对不同内存资源是多线程。

也就是说加锁只对于线程访问相同内存资源,对于访问不同的内存资源不影响

对线程访问同一个内存资源代码不加锁

对线程访问同一内存资源加锁

对同一内存资源可以是 方法,代码块,对象

synchronized 修饰方法

如上图所示

synchronized 修饰代码块

synchronized(this){
    //**代码块**//
}

 synchronized 修饰对象

synchronized(MultiThreading.class){
    
}
synchronized(对象名){

}

线程的五种状态

创建状态

创建了线程对象,已经有相应的内存空间,但处于不可运行状态。 例如:Thread thread=new Thread()

 就绪状态

启动了线程,也就是 start()

 运行状态

调用run()方法后

 阻塞状态

该线程处于阻塞状态。sleep() , suspend(), wait()等会使线程进入阻塞状态,直到过了sleep()时间,调用resume(),调用notify()等

suspend() 与 resume()  暂停与暂停后继续

run()中加入suspend(),程序运行到suspend()后,线程中断,进入阻塞状态,等到线程对象调用sleep()与resume()后,线程继续
suspend()不会释放所持锁,如果resume()在suspend()之前,会造成死锁,已弃用

//i==3时会停一秒钟,再输出3,4,5
//如果注释掉resume(),程序将输出1,2 然后一直处于等待状态
public class MultiThreading implements Runnable{ @Override public synchronized void run() { for (int i = 1; i <= 5; i++) { if (i ==3) { Thread.currentThread().suspend(); } System.out.println(String.format("i:%s 线程:%s", i, Thread.currentThread().getName())); } } public static void main(String args[]) throws InterruptedException { MultiThreading a = new MultiThreading(); Thread one = new Thread(a); one.start();       Thread.sleep(1000);     one.resume(); } }

 wite() 与 notify()


wait() 与 notify() 必须要在相同对象锁下调用(在synchronized(){}内调用),不然会抛出java.lang.IllegalMonitorStateException的异常


synchronized(this) 指当前对象, synchronized(对象) 指该对象锁


wait()与notify()是Object对象就有的,也就是说所有对象都有


调用wait() 会释放该锁,该线程进入阻塞,但是其它线程可以接管该锁; 不同于suspend() ,suspend()不会释放锁,线程会一直挂在那并且其它线程无法继续访问与它的相同内存资源,直到等到resume();


wait()相比于suspend()不会造成死锁


join()
等待该线程完成后,才能继续运行join()之后的程序

加锁下输出1~10

public class MultiThreading implements Runnable{
    public synchronized void run() {    
    	int i=1;
    	while(i<10) {
    		i++;
    	}
    }

    public static void main(String[] args) {
    	MultiThreading a = new MultiThreading();
    	Thread threadOne = new Thread(a);
    	Thread threadTwo = new Thread(a);
        threadOne.start();
        threadTwo.start();
    }
}

 结果是1 2 3 4 5 6 7 8 9  1 2 3 4 5 6 7 8 9

它只能先执行完threadOne ,然后再执行threadtwo

加锁并加wait()与notify() 使输出结果为 112233445566778899

public class MultiThreading implements Runnable{
    public synchronized void run() {    
    	int i=1;
    	while(i<10) {
    		this.notifyAll();
    		try {
			this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    		System.out.println(i);
    		i++;
    	}
    	this.notifyAll();
    }

    public static void main(String[] args) {
    	MultiThreading a = new MultiThreading();
    	Thread threadOne = new Thread(a);
    	Thread threadTwo = new Thread(a);
        threadOne.start();
        threadTwo.start();
    }
}

通过往实现的Runnable接口的类 加入对象锁 Object lock ,

实现多个线程的调度

如下是输出 1212121212121212

public class MultiThreading implements Runnable{
	private int num;
	private Object lock;
	public MultiThreading(int num,Object lock) {
		this.num = num;
		this.lock=lock;
	}
    public  void run() {    
    	synchronized(lock) {
	    	int i=1;
	    	while(i<10) {
	    		lock.notifyAll();
	    		try {
				lock.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
	    		System.out.println(num);
	    		i++;
	    	}
	    	lock.notifyAll();
    	}
    }

    public static void main(String[] args) {
    	Object lock =new Object();
    	MultiThreading a_one = new MultiThreading(1,lock);
    	MultiThreading a_two = new MultiThreading(2,lock);

    	Thread threadOne = new Thread(a_one);
    	Thread threadTwo = new Thread(a_two);
        threadOne.start();
        threadTwo.start();
    }
}

 不加wait()与notify()的结果是  先执行完线程threadOne,后执行threadTwo