线程死锁简单示例
package second.study; public class Test { public static void main(String[] args) { Thread thread1 = new Thread(new DeadLock(true)); Thread thread2 = new Thread(new DeadLock(false)); thread1.start(); thread2.start(); } } class DeadLock implements Runnable { private boolean flag; DeadLock(boolean flag) { this.flag = flag; } @Override public void run() { if (flag) { while (true) { synchronized (Lock.obj1) { System.out.println("if Lock1"); synchronized (Lock.obj2) { System.out.println("if Lock2"); } } } } else { while (true) { synchronized (Lock.obj2) { System.out.println("else Lock2"); synchronized (Lock.obj1) { System.out.println("else Lock1"); } } } } } } class Lock { static Object obj1 = new Object(); static Object obj2 = new Object(); }
多线程间通信
解决线程间通信的安全问题的关键是,在操作共享数据时使用同一把锁将共享数据进行锁定!这样,别的线程就算获得了cpu的执行权,没有锁也无法运行共享数据。
wait(); notify(); notifyAll();都使用在同步中,因为要对持有监视器(锁)的线程进行操作。只有锁对象内才具有wait()等方法。
//单生产者单消费者多线程代码package second.study; public class Test { public static void main(String[] args) { Person p = new Person(); new Thread(new Input(p)).start(); new Thread(new Output(p)).start(); } } class Person { private String name; private String sex; private boolean flag = false; public synchronized void set(String name, String sex) {//在锁对象内使用wait()和notify()方法 if (flag) {//if语句只适用于单生产者单消费者问题 try { this.wait(); } catch (Exception ex) { } } this.name = name; this.sex = sex; flag = true; this.notify();//notify()语句也只适用于单生产者单消费者问题 } public synchronized void get() { if (!flag) { try { this.wait(); } catch (Exception ex) { } } System.out.println(name + "...." + sex); flag = false; this.notify(); } } class Input implements Runnable { private Person p; public Input(Person p) { this.p = p; } @Override public void run() { int x = 0; while (true) { if (x == 0) { p.set("John", "man"); } else { p.set("丽丽", "女女女女"); } x = (x + 1) % 2; } } } class Output implements Runnable { Person p; public Output(Person p) { this.p = p; } @Override public void run() { while (true) { p.get(); } } }
多生产者多消费者问题
package second.study; public class Test { public static void main(String[] args) { Resource resource = new Resource(); new Thread(new Producer(resource)).start(); new Thread(new Producer(resource)).start(); new Thread(new Consumer(resource)).start(); new Thread(new Consumer(resource)).start(); } } class Resource{ private int count; private String name; private boolean flag = false; public synchronized void set(String name) { while(flag) { try { wait(); }catch(InterruptedException ex) { } } this.name = name + "--" + count++; System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name); flag = true; this.notifyAll(); } public synchronized void out() { while(!flag) { try { wait(); }catch(InterruptedException ex) { } } System.out.println(Thread.currentThread().getName()+"......消费者......"+this.name); flag = false; this.notifyAll(); } } class Producer implements Runnable{ private Resource res; public Producer(Resource res) { this.res = res; } @Override public void run() { while(true) { res.set("商品"); } } } class Consumer implements Runnable{ private Resource res; public Consumer(Resource res) { this.res = res; } @Override public void run() { while(true) { res.out(); } } }
在JDK1.5以后,将监视器对象(锁)和监视器方法(wait();等)替换成了Lock接口对象和Condition接口对象。并且该监视器方法依然可以通过锁对象获取,并且可以创建多个锁的监视器方法对象,可以理解为可以创建多个线程池(自己的理解),用于唤醒相应线程池中的一个线程,提高速度。
package second.study; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Test { public static void main(String[] args) { Resource resource = new Resource(); new Thread(new Producer(resource)).start(); new Thread(new Producer(resource)).start(); new Thread(new Consumer(resource)).start(); new Thread(new Consumer(resource)).start(); } } class Resource { private int count; private String name; private boolean flag = false; Lock lock = new ReentrantLock();//Lock是一个接口,需要使用其可创建对象的子类; Condition condition_pro = lock.newCondition();//使用Lock对象中的方法获取监视器方法对象 Condition condition_con = lock.newCondition(); public void set(String name) { lock.lock(); try { while (flag) { condition_pro.await();//线程0线程1进入一个线程池 } this.name = name + "--" + count++; System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name); flag = true; condition_con.signal(); } catch (InterruptedException ex) { } finally { lock.unlock();// 资源一定要释放 } } public void out() { lock.lock(); try { while (!flag) { condition_con.await();//线程2和线程2进去一个线程池 } System.out.println(Thread.currentThread().getName() + "......消费者......" + this.name); flag = false; condition_pro.signal(); }catch(InterruptedException ex) { }finally { lock.unlock(); } } } class Producer implements Runnable { private Resource res; public Producer(Resource res) { this.res = res; } @Override public void run() { while (true) { res.set("商品"); } } } class Consumer implements Runnable { private Resource res; public Consumer(Resource res) { this.res = res; } @Override public void run() { while (true) { res.out(); } } }
如何停止线程?
stop方法已经过时,那么停止线程只有一种,run方法结束。可以通过在主线程来控制run()方法中的标记来控制其他线程的结束。当其他线程中有wait();sleep();方法时,可能其他线程无法判断标记而使线程处于冻结状态,这时,可以使用Thread类中的interrupt()方法。当主线程执行到interrupt方法来中断线程,但是其他同步线程没有使用wait方法,这时interrupt方法对该线程不起作用,但是主线程会一直监视该线程的状态,当该线程执行到了wait方法,会立即响应中断,引发interruptException异常。然后会以下是测试代码:
package second.study; public class Test { public static void main(String[] args) { StopThread stopThread = new StopThread(); Thread t1 = new Thread(stopThread); Thread t2 = new Thread(stopThread); t1.start(); t2.start(); int num = 0; while(true) { if(num == 60) { t1.interrupt(); t2.interrupt(); System.out.println("main interrupt");//判定主线程在t1和t2线程执行wait方法之前先执行了interrupt方法。 break; } num++; System.out.println(Thread.currentThread().getName() + "......" + num); } } } class StopThread implements Runnable{ private boolean flag = true; @Override public synchronized void run() { while(flag) { try { int num = 0; while(true) { System.out.println(Thread.currentThread().getName() + "..." + num); if(num == 100) { System.out.println(Thread.currentThread().getName() + "..." + "run"); wait(); } num++; } }catch(InterruptedException ex) { System.out.println(Thread.currentThread().getName() + "..." + "Exception"); flag = false;//结束当前线程 } } } public void changeFlag() { flag = false; } }
守护线程
也称为后台线程,当前程线程执行完毕后,后台线程会自动结束。当正在运行的线程全部为首部线程时,JVM退出。
Thread类中的setDaemon方法。在开启线程(使用start()方法)前使用。
多线程的Join方法
当A线程执行到了B线程的.join方法时,A就会等待,当B线程运行结束后,A线程才会执行。
join可以用来临时加入线程。
线程优先级
线程的优先级分为10级,可以使用setPriority(Thread.MAX_PRIORITY or Thread.MIN_PRIORITY or Thread.NORM_PRIORITY),来设置线程的优先级。
原文地址:https://www.cnblogs.com/star-491849224/p/12489248.html