线程死锁简单示例
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),来设置线程的优先级。
来源:oschina
链接:https://my.oschina.net/u/4264169/blog/4185901