多线程--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