您的位置:首页 > 编程语言 > Java开发

Java的第一个坑,多线程入门

2017-11-15 11:53 323 查看
起因是一道笔试题:

http://edisonxu.org/2017/03/02/java-thread-communication.html#comments

(上面这篇文章中提到的关于volatile的答案似乎有问题)

几个坑的地方:

1. wait() 和notify() 一定是在synchronized()块中出现

 wait() 发生时会当前线程释放锁

 notify()发生时,会?

2. notify() 出现在wait() 之前则无效(和条件变量的区别)

3. Integer虽然可以调用wait(),notify(),但是由于赋新值时会改变对象,所以不能用在这里,要自己定义一个类似的东西

我的代码:

1,Ojbect,synchronized,wait,notify版

package mytest;

public class ThreadTest {
static class ThreadNum{
public int i;
public ThreadNum(int value){
i=value;
}
}
private Object w1=new Object ();
private Object w2=new Object();
private Object o=new Object();
private ThreadNum cur=new ThreadNum(1);//must use self-define type

public Runnable newThreadOne() {
return new Runnable() {
public void run() {
try {
for (int i = 0; i < 52; i=i+2) {
synchronized (cur) {//must inside synchronized block
if(cur.i==2)//从逻辑上来说,只有两个线程if应该没问题;但是有个叫Spurious wakeup 的东西要求这个地方一定要用while,然而懒得改了
{
cur.wait();
}
System.out.print(i+1);
System.out.print(i+2);
cur.i=2;
cur.notify();
}
}
} catch (InterruptedException e) {
System.out.println("Oops...");
}
}
};
}
public Runnable newThreadTwo() {
return new Runnable() {
public void run() {
try {
for (int i = 0; i < 26; i++) {
synchronized (cur) {
if(cur.i==1)
{
cur.wait();
}
System.out.print((char)('a'+i));
cur.i=1;
cur.notify();
}
}
} catch (InterruptedException e) {
System.out.println("Oops...");
}
}
};
}

public static void main(String args[]) throws InterruptedException {
/*
Object o=new Object();
synchronized (o) {
o.notify();
System.out.println("notified");
o.wait();
System.out.println("wait");
}*/

ThreadTest test = new ThreadTest();
Thread t1=new Thread(test.newThreadOne());
Thread t2=new Thread(test.newThreadTwo());
t1.start();
t2.start();

}
}


2.condition,lock,unlock,await,signal版

java的signal函数似乎一定是要持有锁的线程调用,这点和C的
pthread_cond_t
不同

package mytest;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionTest {
private Lock lock=new ReentrantLock(true);
private Condition condition1=lock.newCondition();
private Condition condition2=lock.newCondition();
private int thread_to_run=1;
public Runnable newThreadOne() {
return new Runnable() {
public void run() {
try {
for (int i = 0; i < 52; i=i+2) {
synchronized (lock) {
while(thread_to_run!=1){
condition1.wait();
}
System.out.print(i+1);
System.out.print(i+2);
condition2.signal();
}
}
} catch (InterruptedException e) {
System.out.println("Oops...");
}
}
};
}
public Runnable newThreadTwo() {
return new Runnable() {
public void run() {
try {
for (int i = 0; i < 26; i++) {
synchronized (lock) {
while(thread_to_run!=2){
condition2.await();
}
System.out.print((char)('a'+i));
condition1.signal();
}
}
} catch (InterruptedException e) {
System.out.println("Oops...");
}
}
};
}

public static void main(String args[]) throws InterruptedException {
/*
Lock lock=new ReentrantLock(true);
Condition condition1=lock.newCondition();
condition1.signal();
System.out.println("signal");
lock.lock();
System.out.println("before wait");
condition1.await();
System.out.println("wait");
condition1.signal();
System.out.println("signal");
lock.unlock();
*/

ThreadTest test = new ThreadTest();
Thread t1=new Thread(test.newThreadOne());
Thread t2=new Thread(test.newThreadTwo());
t1.start();
t2.start();
t1.join();
t2.join();

}
}


3.信号量 semaphore,acquire,release

个人感觉信号量的版本最简单,因为这是一个关于顺序控制的问题,所以信号量会直接管理一个相关的计数器,不用像前面的程序那样需要自己控制另外一个变量

package mytest;

import java.util.concurrent.Semaphore;

public class SemaphoreTest {
static class ThreadNum{
public int i;
public ThreadNum(int value){
i=value;
}
}
private Semaphore w1=new Semaphore(1);
private Semaphore w2=new Semaphore(0);

public Runnable newThreadOne() {
return new Runnable() {
public void run() {
try {
for (int i = 0; i < 52; i=i+2) {
w1.acquire();
System.out.print(i+1);
System.out.print(i+2);
w2.release();
}
} catch (InterruptedException e) {
System.out.println("Oops...");
}
}
};
}
public Runnable newThreadTwo() {
return new Runnable() {
public void run() {
try {
for (int i = 0; i < 26; i++) {
w2.acquire();
System.out.print((char)('a'+i));
w1.release();

}
} catch (InterruptedException e) {
System.out.println("Oops...");
}
}
};
}

public static void main(String args[]) throws InterruptedException {

ThreadTest test = new ThreadTest();
Thread t1=new Thread(test.newThreadOne());
Thread t2=new Thread(test.newThreadTwo());

t1.start();
t2.start();
t1.join();
t2.join();

}
}


参考:

1.异常

http://blog.csdn.net/historyasamirror/article/details/6709693

2.条件变量

http://blog.csdn.net/woshixuye/article/details/28283289

3.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: