多线程操作

有两个线程,线程a先打印100下,然后线程b打印十下,然后再a打印。。。。

思路:一定要做到线程和任务分离,把a线程的任务和b线程的任务放到一个类里面来,然后再让这两个线程分别调用这个类就可以了

[code]
package cn.itcast.heima2;


public class TraditionalThreadCommunication {

/**
* @param args
*/
public static void main(String[] args) {

final Business business = new Business();
new Thread(
new Runnable() {

@Override
public void run() {

for(int i=1;i<=50;i++){
business.sub(i);
}

}
}
).start();

for(int i=1;i<=50;i++){
business.main(i);
}

}

}
class Business {
private String executeMethodName ="sub";
public synchronized void sub(int i){
while(!executeMethodName.equals("sub")){//如果不该我执行
try {
this.wait();//如果不该我执行
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for(int j=1;j<=10;j++){
System.out.println("sub thread sequence of " + j + ",loop of " + i);
}
executeMethodName = "main";
this.notify();
}

public synchronized void main(int i){
while(!executeMethodName.equals("main")){//如果不该我执行
try {
this.wait(); //我就等等
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

for(int j=1;j<=100;j++){
System.out.println("main thread sequence of " + j + ",loop of " + i);
}

//令牌标示成sub,并去叫醒sub
executeMethodName = "sub";
this.notify();
}
}

[/code]
如果是三个交替的弄,则可以使用下面的方法,使用wait和notify,那么一共只有一个等待区,如果是使用condition,那么会明确多个等待区,这样不会唤醒不该被唤醒的线程
[code]
package cn.itcast.heima2;

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

public class ThreeConditionCommunication {

/**
* @param args
*/
public static void main(String[] args) {

final Business business = new Business();
new Thread(
new Runnable() {

@Override
public void run() {

for(int i=1;i<=50;i++){
business.sub2(i);
}

}
}
).start();

new Thread(
new Runnable() {

@Override
public void run() {

for(int i=1;i<=50;i++){
business.sub3(i);
}

}
}
).start();

for(int i=1;i<=50;i++){
business.main(i);
}

}

static class Business {
Lock lock = new ReentrantLock();
Condition conditionMain = lock.newCondition();
Condition conditionSub2 = lock.newCondition();
Condition conditionSub3 = lock.newCondition();
private String executeMethodName = "main";
public void sub2(int i){
lock.lock(); //所只能保证只有一个人能进来,但是不能保证进来的人是谁
try{
while(!executeMethodName.equals("sub2")){//虽然我抢到了锁,但是如果不是我执行,我还是得等待
try {
conditionSub2.await();//我到2区等待
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for(int j=1;j<=10;j++){
System.out.println("sub2 thread sequence of " + j + ",loop of " + i);
}
executeMethodName="sub3";
conditionSub3.signal();
}finally{
lock.unlock();
}
}

public void sub3(int i){
lock.lock();
try{
while(!executeMethodName.equals("sub3")){
try {
conditionSub3.await();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for(int j=1;j<=20;j++){
System.out.println("sub3 thread sequence of " + j + ",loop of " + i);
}
executeMethodName="main";
conditionMain.signal();
}finally{
lock.unlock();
}
}

public void main(int i){
lock.lock();
try{
while(!executeMethodName.equals("main")){
try {
conditionMain.await();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for(int j=1;j<=100;j++){
System.out.println("main thread sequence of " + j + ",loop of " + i);
}
executeMethodName = "sub2";
conditionSub2.signal();
}finally{
lock.unlock();
}
}

}
}

[/code]

阻塞队列
[code]
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class BoundedBuffer {//阻塞队列
final Lock lock = new ReentrantLock();
final Condition puterWaitArea = lock.newCondition(); //放入者等候区
final Condition takerWaitArea = lock.newCondition(); //消费者等候区

final Object[] items = new Object[100]; //队列
int putptr, takeptr, count;

public void put(Object x) throws InterruptedException {
lock.lock();//一次只能一个线程进入
try {
while (count == items.length) //线程进入后,查看准入条件
puterWaitArea.await();

items[putptr] = x;
if (++putptr == items.length) putptr = 0;

++count;//转入条件变化
takerWaitArea.signal();
} finally {
lock.unlock();
}
}

public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)//线程进入后,查看准入条件
takerWaitArea.await();

Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;

--count;
puterWaitArea.signal();
return x;
} finally {
lock.unlock();
}
}
}

[/code]

---------------------------------------------------------------------------------------------------------------------------------------------------------------------
以上的需求是,多个线程 在某个时刻只能有一个线程进入 其中的一个方法,也就是取东西和放东西 只能有一个操作

下面展示,某一个方法可以同时被多个线程调用,而另一个方法只能被一个线程调用。。生产者消费者问题

[code]
package cn.itcast.heima2;

import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockTest {
public static void main(String[] args) {
final Queue3 q3 = new Queue3();
for(int i=0;i<3;i++)
{
new Thread(){
public void run(){
while(true){
q3.get();
}
}

}.start();

new Thread(){
public void run(){
while(true){
q3.put(new Random().nextInt(10000));
}
}

}.start();
}

}
}

class Queue3{
private Object data = null;//共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据。
ReadWriteLock rwl = new ReentrantReadWriteLock();
public void get(){
rwl.readLock().lock();//只有一个准入条件
try {
System.out.println(Thread.currentThread().getName() + " be ready to read data!");
Thread.sleep((long)(Math.random()*1000));
System.out.println(Thread.currentThread().getName() + "have read data :" + data);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
rwl.readLock().unlock();
}
}

public void put(Object data){

rwl.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + " be ready to write data!");
Thread.sleep((long)(Math.random()*1000));
this.data = data;
System.out.println(Thread.currentThread().getName() + " have write data: " + data);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
rwl.writeLock().unlock();
}


}
}

[/code]
[code]
private ReadWriteLock rwl = new ReentrantReadWriteLock();
public Object getData(String key){
rwl.readLock().lock();

Object value = null;
try{
value = cache.get(key);
if(value == null){ //如果没读到,释放读锁,加写锁
rwl.readLock().unlock();

rwl.writeLock().lock();
try{
value = cache.get(key);
if(value==null){ // 防止重复写,只有value为空的时候才能写,
//比如有两个线程到了rwl.writeLock().lock();,第一个线程先拿到写锁,写完后,第二个线程就不应该去写了,所以这里对第二个线程要验证下
value = "aaaa";//实际失去queryDB();
cache.put(key, value);
}
}finally{
rwl.writeLock().unlock();
}
rwl.readLock().lock();
}
}finally{
rwl.readLock().unlock();
}
return value;
}
[/code]
如果要对等待区进行的数量进行控制,则可以使用CountDownLatch
[code]
package cn.itcast.heima2;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountdownLatchTest {

public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final CountDownLatch cdOrder = new CountDownLatch(1);
final CountDownLatch cdAnswer = new CountDownLatch(3);
for(int i=0;i<3;i++){
Runnable runnable = new Runnable(){
public void run(){
try {
System.out.println("线程" + Thread.currentThread().getName() +
"正准备接受命令");

cdOrder.await();
System.out.println("线程" + Thread.currentThread().getName() +
"已接受命令");
Thread.sleep((long)(Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() +
"回应命令处理结果");
cdAnswer.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
};
service.execute(runnable);
}
try {
Thread.sleep((long)(Math.random()*10000));

System.out.println("线程" + Thread.currentThread().getName() +
"即将发布命令");
cdOrder.countDown();//这个方法里面有唤醒代码,先把数字减一,如果数字为0则唤醒线程,这相当于对notify的封装,条件被封装到了countDown方法里面,有条件的唤醒
System.out.println("线程" + Thread.currentThread().getName() +
"已发送命令,正在等待结果");
cdAnswer.await();
System.out.println("线程" + Thread.currentThread().getName() +
"已收到所有响应结果");
} catch (Exception e) {
e.printStackTrace();
}
service.shutdown();
}
}

[/code]
CyclicBarrier 自己的实现,CyclicBarrier就是控制缓冲区中的数目,到了一定的数目才唤醒,await里面会有计数器,当计数器到达指定值则调用notifyAll
[code]
package cn.itcast.heima2;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class CyclicBarrierTest {

public static void main(String[] args) {
test();
}
static int count=0;
static int step = 1;
public static void test(){
ExecutorService service = Executors.newCachedThreadPool();
final Lock lock = new ReentrantLock();

final Condition con = lock.newCondition();
for(int i=0;i<3;i++){
Runnable runnable = new Runnable(){
public void run(){
lock.lock();
try {
if(step==1){
System.out.println("线程" + Thread.currentThread().getName() +
"即将到达集合地点1,当前已有" + (count+1) + "个已经到达," + (count==2?"都到齐了,继续走啊":"正在等候"));
count++;
if(count<3)
con.await();
else{
count =0 ;
step =2;
con.signalAll();
}
}
if(step==2){
System.out.println("线程" + Thread.currentThread().getName() +
"即将到达集合地点2,当前已有" + (count+1) + "个已经到达," + (count==2?"都到齐了,继续走啊":"正在等候"));
count++;
if(count<3)
con.await();
else{
count =0 ;
step =3;
con.signalAll();
}
}
if(step==3){
System.out.println("线程" + Thread.currentThread().getName() +
"即将到达集合地点3,当前已有" + (count+1) + "个已经到达," + (count==2?"都到齐了,继续走啊":"正在等候"));
count++;
if(count<3)
con.await();
else{
count =0 ;
step =4;
con.signalAll();
}
}
lock.unlock();
} catch (Exception e) {
e.printStackTrace();
}
}
};
service.execute(runnable);
}
service.shutdown();
}
}

[/code]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值