`
justinyao
  • 浏览: 39650 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

java 多线程小练

阅读更多
在网上看到这样一道试题,关于多线程的,拿来小练一下
题目:有一个南北向的桥,只能容纳一个人,现桥的两边分别有10人和12人,编制一个多线程序让这些人到达对岸,每个人用一个线程表示,桥为共享资源。在过桥的过程中显示谁在过桥及其走向。

以下是我的代码
package test;

public class MyThread3 extends Thread {

	private String name;
	private String direction;

	public MyThread3(String name, String direction) {
		this.direction = direction;
		this.name = name;
		System.out.println(direction + "方的" + name + "开始过桥...");
	}

	public synchronized void run() {
		try {
			Thread.currentThread().sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(this.direction + "方的" + this.name + "过桥完成!"+"---"+Thread.currentThread().getName());
	}

	public static void main(String[] args) throws InterruptedException {
		MyThread3[] ths = new MyThread3[12];
		int i = 0;
		boolean flag = true;
		while (i <ths.length) {
			if (i < 10)
				ths[i] = new MyThread3("第" + (i+1) + "个人",flag == false ? "北" : "南");
			else
				ths[i] = new MyThread3("第" + (i+1) + "个人", "南");
			ths[i].start();
			ths[i].join();
			ths[i].sleep(1000);
			flag = !flag;
			if (flag == true||i>=10)
				i++;
		}
	}
}


对于synchronized 关键字用法还没完全搞懂,在run中可有可无的
分享到:
评论
22 楼 咖啡豆子 2011-05-16  
yongqi 写道
我也写一个,我认为是人在过桥,桥只是一个资源,不知道是否正确,请大家指正

package org.wyq.test;

public class MyTest {

	public static void main(String[] args) {

		Bridge bridge = new Bridge();
		Person[] nperson = new Person[12]; // 站在北边的人
		Person[] sperson = new Person[10]; // 站在南边的人

		for (int i = 0; i < nperson.length; i++) {
			nperson[i] = new Person("np" + i, bridge, -1);
			nperson[i].start();
		}
		for (int i = 0; i < nperson.length; i++) {
			nperson[i] = new Person("sp" + i, bridge, 1);
			nperson[i].start();
		}
	}
}

/**
 * 人
 */
class Person extends Thread {
	private String name;
	private Bridge bridge;
	private int flag;;

	public Person() {
	}

	public Person(String name, Bridge bridge, int flag) {
		this.name = name;
		this.bridge = bridge;
		this.flag = flag;
	}

	public void run() {
		crossBridge();
	}

	/**
	 * 过桥
	 */
	public void crossBridge() {

		synchronized (bridge) {
			System.out.print(name + " 从" + (flag > 0 ? "南" : "北") + "面过桥");
			try {
				Thread.sleep(500); // 过桥使用500ms
			} catch (InterruptedException e) {
			}
			System.out.println("\t\t到达" + (flag > 0 ? "北" : "南") + "面");
		}

	}
}

/**
 * 桥
 */
class Bridge {
}

恩,同意,桥只是共享资源,不必关心方向问题
21 楼 Technoboy 2011-05-16  
这个贴的回复,真是杀人啊
20 楼 yongqi 2011-05-15  
我也写一个,我认为是人在过桥,桥只是一个资源,不知道是否正确,请大家指正

package org.wyq.test;

public class MyTest {

	public static void main(String[] args) {

		Bridge bridge = new Bridge();
		Person[] nperson = new Person[12]; // 站在北边的人
		Person[] sperson = new Person[10]; // 站在南边的人

		for (int i = 0; i < nperson.length; i++) {
			nperson[i] = new Person("np" + i, bridge, -1);
			nperson[i].start();
		}
		for (int i = 0; i < nperson.length; i++) {
			nperson[i] = new Person("sp" + i, bridge, 1);
			nperson[i].start();
		}
	}
}

/**
 * 人
 */
class Person extends Thread {
	private String name;
	private Bridge bridge;
	private int flag;;

	public Person() {
	}

	public Person(String name, Bridge bridge, int flag) {
		this.name = name;
		this.bridge = bridge;
		this.flag = flag;
	}

	public void run() {
		crossBridge();
	}

	/**
	 * 过桥
	 */
	public void crossBridge() {

		synchronized (bridge) {
			System.out.print(name + " 从" + (flag > 0 ? "南" : "北") + "面过桥");
			try {
				Thread.sleep(500); // 过桥使用500ms
			} catch (InterruptedException e) {
			}
			System.out.println("\t\t到达" + (flag > 0 ? "北" : "南") + "面");
		}

	}
}

/**
 * 桥
 */
class Bridge {
}
19 楼 咖啡豆子 2011-05-15  
共享资源通常就是要锁定的对象,每个人启一个线程,用wait/notify协作,桥作为互斥对象,就是要被synchronized的锁对象
18 楼 yangyi 2011-05-14  
import threading
import time
from collections import deque

class Person(threading.Thread):
    def __init__(self, id, msg):
        threading.Thread.__init__(self)
        self.id = id
        self.msg = msg
    def run(self):
        cross(self)
    def cross(self):
        print(str(self.id) + "\t" + self.msg)

class PersonPool(threading.Thread):
    canCross = threading.RLock()
    def __init__(self):
        threading.Thread.__init__(self)
        self.persons = deque([])
        self.shutdown = False
    def add(self, person):
        self.persons.append(person)
    def stop(self):
        self.shutdown = True
    def run(self):
        self.waitForPerson()
    def waitForPerson(self):
        while self.shutdown == False:
            PersonPool.canCross.acquire()
            while len(self.persons) != 0:
                person = self.persons.popleft()
                person.cross()
            time.sleep(1)
            PersonPool.canCross.release()

if __name__ == "__main__":
    nsPool = PersonPool()
    snPool = PersonPool()

    snPool.start()
    nsPool.start()

    for i in xrange(0, 10):
        snPool.add(Person(i, "From North To South"))
    for j in xrange(0, 12):
        snPool.add(Person(j, "From South To North"))
17 楼 marshaldong 2011-05-14  
panpan123mail 写道
线程池写了代码,也实现了其功能,但老觉得没把线程池的作用充分发挥出来,请教各位
public class ThreadTestOne implements Runnable
{
    private ExecutorService pool;
    
    private int poolSize;
    
    private int NorthToSouth;
    
    private int SouthToNorth;
    
    public ThreadTestOne(int NorthToSouth, int SouthToNorth)
    {
        this.NorthToSouth = NorthToSouth;
        this.SouthToNorth = SouthToNorth;
        this.poolSize = Math.max(NorthToSouth, SouthToNorth);
        pool = Executors.newFixedThreadPool(poolSize);
    }
    
    public synchronized void run()
    {
        boolean flag = true;
        for (int i = 0; i < poolSize; i++)
        {
            if (i < Math.min(NorthToSouth, SouthToNorth))
            {
                pool.execute(new Handler("第" + (i + 1) + "个人", flag == false ? "北" : "南"));
            }
            else
            {
                pool.execute(new Handler("第" + (i + 1) + "个人", "南"));
            }
            try
            {
                Thread.sleep(2000);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            
            flag = !flag;
        }
        pool.shutdown();
    }
    
    class Handler implements Runnable
    {
        private String name;
        
        private String direction;
        
        public Handler(String name, String direction)
        {
            this.direction = direction;
            this.name = name;
            System.out.println(direction + "方的" + name + "开始过桥...");
        }
        
        public void run()
        {
            System.out.println(this.direction + "方的" + this.name + "过桥完成!" + "---" + Thread.currentThread().getName());
        }
    }
    
    public static void main(String[] args)
        throws InterruptedException
    {
        //test
        ThreadTestOne threadTestOne = new ThreadTestOne(12, 10);
        threadTestOne.run();
    }
}

有这感觉,线程池用在大量线程系统,和更复杂的线程交互可能更有用,简单的线程交互用传统的方式会较简单,不过好像代码量也差不多。
16 楼 marshaldong 2011-05-14  
freish 写道
如果是22个人的共享,用一下ReentrantLock就行,两类人用ReentrantReadWriteLock就行


既然JDK1.5有更安全的Thread使用方式,也是推荐的使用方式,我们就应多使用这个特性来编写多线程程序,以下是我试写的,分享下,和大家共同进步,希望有更好的建议:
package dong.concurrency;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Bridge {
	final ReentrantLock lock = new ReentrantLock();
	final Condition codition = lock.newCondition();
	volatile boolean isFree = true;
	ExecutorService exec = Executors.newFixedThreadPool(22);

	public Bridge() {
	}

	private void generatePerson() {
		for (int i = 1; i <= 22; i++) {
			if (i <= 10)
				exec.execute(new Person(this, Direction.values()[0], i));
			else
				exec.execute(new Person(this, Direction.values()[1], i));
		}
	}

	public static void main(String[] args) {
		Bridge bridge = new Bridge();
		bridge.generatePerson();
		bridge.exec.shutdown();
	}
}

enum Direction {
	SOUTHTONORTH("South---->North"), NORTHTOSOUTH("North--->South");
	private String desc;

	Direction(String dirc) {
		desc = dirc;
	}

	@Override
	public String toString() {
		return desc;
	}

}

class Person implements Runnable {
	private Bridge bridge;
	private Direction direction;
	private final int id;
	private static Random rand = new Random();

	public Person(Bridge bridge, Direction direction, int id) {
		this.bridge = bridge;
		this.direction = direction;
		this.id = id;
	}

	@Override
	public String toString() {
		return "Person " + id + " crossed bridge from " + direction.toString();
	}

	@Override
	public void run() {
		crossBridge();
	}

	private void crossBridge() {

		bridge.lock.lock();
		try {
			try {
				while (!bridge.isFree)
					bridge.codition.await();
				System.out.println(toString());
				bridge.isFree = true;
				bridge.codition.signalAll();
				TimeUnit.MILLISECONDS.sleep(rand.nextInt(500));
			} catch (Exception e) {
				e.printStackTrace();
			}
		} finally {
			bridge.lock.unlock();
		}
	}
}

15 楼 panpan123mail 2011-05-14  
线程池写了代码,也实现了其功能,但老觉得没把线程池的作用充分发挥出来,请教各位
public class ThreadTestOne implements Runnable
{
    private ExecutorService pool;
    
    private int poolSize;
    
    private int NorthToSouth;
    
    private int SouthToNorth;
    
    public ThreadTestOne(int NorthToSouth, int SouthToNorth)
    {
        this.NorthToSouth = NorthToSouth;
        this.SouthToNorth = SouthToNorth;
        this.poolSize = Math.max(NorthToSouth, SouthToNorth);
        pool = Executors.newFixedThreadPool(poolSize);
    }
    
    public synchronized void run()
    {
        boolean flag = true;
        for (int i = 0; i < poolSize; i++)
        {
            if (i < Math.min(NorthToSouth, SouthToNorth))
            {
                pool.execute(new Handler("第" + (i + 1) + "个人", flag == false ? "北" : "南"));
            }
            else
            {
                pool.execute(new Handler("第" + (i + 1) + "个人", "南"));
            }
            try
            {
                Thread.sleep(2000);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            
            flag = !flag;
        }
        pool.shutdown();
    }
    
    class Handler implements Runnable
    {
        private String name;
        
        private String direction;
        
        public Handler(String name, String direction)
        {
            this.direction = direction;
            this.name = name;
            System.out.println(direction + "方的" + name + "开始过桥...");
        }
        
        public void run()
        {
            System.out.println(this.direction + "方的" + this.name + "过桥完成!" + "---" + Thread.currentThread().getName());
        }
    }
    
    public static void main(String[] args)
        throws InterruptedException
    {
        //test
        ThreadTestOne threadTestOne = new ThreadTestOne(12, 10);
        threadTestOne.run();
    }
}
14 楼 沈冠军 2011-05-13  
额,受教了
13 楼 la_ka 2011-05-13  
LZ第一个代码比较符合你题目。。。。。。呵呵
12 楼 lyl290932857 2011-05-13  
既然桥是公共资源,我想synchronized就作用到桥上比较好点。
class GapBridge implements Runnable {
	
	//桥是公共资源,而且是单向通道因此需要被锁定
	private Object obj;
	//方向判断
	private boolean flag;
	
	public GapBridge (Object obj, boolean flag){
		this.obj = obj;
		this.flag = flag;
	}
	
	@Override
	public void run() {
		synchronized (obj) {
			try {
				Thread.sleep(700);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if(flag){
				System.out.println("第" + Thread.currentThread().getName() + "从北向南过桥!");
			}else{
				System.out.println("第" + Thread.currentThread().getName() + "从南向北过桥!");
			}
		}
	}
}
11 楼 tenderuser 2011-05-13  
justinyao 写道
在网上看到这样一道试题,关于多线程的,拿来小练一下
题目:有一个南北向的桥,只能容纳一个人,现桥的两边分别有10人和12人,编制一个多线程序让这些人到达对岸,每个人用一个线程表示,桥为共享资源。在过桥的过程中显示谁在过桥及其走向。

以下是我的代码
package test;

public class MyThread3 extends Thread {

	private String name;
	private String direction;

	public MyThread3(String name, String direction) {
		this.direction = direction;
		this.name = name;
		System.out.println(direction + "方的" + name + "开始过桥...");
	}

	public synchronized void run() {
		try {
			Thread.currentThread().sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(this.direction + "方的" + this.name + "过桥完成!"+"---"+Thread.currentThread().getName());
	}

	public static void main(String[] args) throws InterruptedException {
		MyThread3[] ths = new MyThread3[12];
		int i = 0;
		boolean flag = true;
		while (i <ths.length) {
			if (i < 10)
				ths[i] = new MyThread3("第" + (i+1) + "个人",flag == false ? "北" : "南");
			else
				ths[i] = new MyThread3("第" + (i+1) + "个人", "南");
			ths[i].start();
			ths[i].join();
			ths[i].sleep(1000);
			flag = !flag;
			if (flag == true||i>=10)
				i++;
		}
	}
}


对于synchronized 关键字用法还没完全搞懂,在run中可有可无的



额 。。。 lz这段代码貌似和线程锁没什么关系嘛。。。。就一个flag标签控制南北两个方向交叉过河。。。。。
synchronized 关键字用来声明锁。 synchronized有两种用法:
一种:synchronized 放在方法前。用来加锁当前对象。相当于method{synchronized(this){}}
第二种:synchronized语句块。
   synchronized(source){} 表示在执行synchronized语句块中的语句时,需要等待source的资源锁。source 一般可以为this 、Xxx.class。

小白的理解, 期待大牛斧正!!!!  
10 楼 Josun 2011-05-13  
牛人好多,我看到线程就晕倒。
9 楼 javadaydayup 2011-05-13  
楼主这个是类似经典的生产者消费者问题了

如果定义,南边到北边一个人后,紧接着北边到南边一个人,相互交替,才有点意思啊,否则没有突出这个共享桥的概念啊
代码如下:此时南到北,和北到南的人数一致,如果不一致得改代码
public class GapBridge {


public static void main(String[] args) {
Bridge bridge = new Bridge();
SourceToNorth stn = new SourceToNorth(bridge);
new Thread(stn).start();
NorthToSource nts = new NorthToSource(bridge);
new Thread(nts).start();

}
}

class Bridge {
/**
* 定义当direction 为-1时,为南到北,否则为北到南,
* 如果这样定义,则是南边去北边一个,再北边去南边一个,交替
*/
private int direction = -1;

public  synchronized  void sourceToNorth(int count) throws InterruptedException{
//表示已有南去北,等待北去南
if(this.direction == -1){
wait();
}
this.direction = -1;
Thread.sleep(500);
System.out.println("当前线程"+Thread.currentThread().getName()+"第"+count+"个南去北***");
notify();
}

public synchronized void northToSource(int count) throws InterruptedException {
//表示已有北去南,等待南去北
if(this.direction != -1 ){
wait();
}
this.direction = count;
Thread.sleep(500);
System.out.println("当前线程"+Thread.currentThread().getName()+"第"+count+"个北去南---");
notify();
}

}


class SourceToNorth implements Runnable{

private Bridge bridge;

public SourceToNorth(Bridge bridge){
this.bridge = bridge;
}

public void run() {
for(int i=1; i<=10; i++ ){
System.out.println("-------------------------------------"+Thread.currentThread().getName()+ "开始过桥--S-N");
try {
bridge.sourceToNorth(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


}

class NorthToSource implements Runnable {
private Bridge bridge;

public NorthToSource(Bridge bridge){
this.bridge = bridge;
}

public void run() {
for(int i=1; i<=10; i++ ){
System.out.println("-------------------------------------"+Thread.currentThread().getName()+ "开始过桥--N-S");
try {
bridge.northToSource(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}



justinyao 写道
在网上看到这样一道试题,关于多线程的,拿来小练一下
题目:有一个南北向的桥,只能容纳一个人,现桥的两边分别有10人和12人,编制一个多线程序让这些人到达对岸,每个人用一个线程表示,桥为共享资源。在过桥的过程中显示谁在过桥及其走向。

以下是我的代码
package test;

public class MyThread3 extends Thread {

	private String name;
	private String direction;

	public MyThread3(String name, String direction) {
		this.direction = direction;
		this.name = name;
		System.out.println(direction + "方的" + name + "开始过桥...");
	}

	public synchronized void run() {
		try {
			Thread.currentThread().sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(this.direction + "方的" + this.name + "过桥完成!"+"---"+Thread.currentThread().getName());
	}

	public static void main(String[] args) throws InterruptedException {
		MyThread3[] ths = new MyThread3[12];
		int i = 0;
		boolean flag = true;
		while (i <ths.length) {
			if (i < 10)
				ths[i] = new MyThread3("第" + (i+1) + "个人",flag == false ? "北" : "南");
			else
				ths[i] = new MyThread3("第" + (i+1) + "个人", "南");
			ths[i].start();
			ths[i].join();
			ths[i].sleep(1000);
			flag = !flag;
			if (flag == true||i>=10)
				i++;
		}
	}
}


对于synchronized 关键字用法还没完全搞懂,在run中可有可无的

8 楼 hell_liul 2011-05-13  
南北共同过桥应该也是公用一个线程吧!! 只能容纳一个人吧!!
7 楼 freish 2011-05-13  
如果是22个人的共享,用一下ReentrantLock就行,两类人用ReentrantReadWriteLock就行
6 楼 freish 2011-05-13  
桥是共享资源是什么意思?


描述有问题啊!是两类人(桥两头)共享还是22个人的共享?不同的理解出来的代码是不一样的
5 楼 Technoboy 2011-05-13  
wuyunbin 写道
谢谢java_user, 如果代码使用inner class,似乎更简练:

class Bridge {
	private static final int TOTAL = 22;
	private int cnt = 0;
    public static void main(String[] args) {  
        Bridge bridge = new Bridge();  
        for (int i = 0; i < TOTAL; i++) {  
            if (i < 10) {  
                new Thread(bridge.new PersonCrossBridge("人" + i,  1) ).start();  
            } else {  
                new Thread(bridge.new PersonCrossBridge("人" + i,  -1)).start();  
            }  
        }  
    }  
    
    public synchronized void crossFromS2N(String person) {  
    	cnt++;
        System.out.print(person + "从南面开始");  
        try {  
            //模拟过桥  
            Thread.sleep(500);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        System.out.println("---到达北面, 共过" +cnt + "人");  
    }  
  
    public synchronized void crossFromN2S(String person) {  
    	cnt++;
        System.out.print(person + "从北面开始");
        try {  
            //模拟过桥  
            Thread.sleep(500);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        System.out.println("---到达南面, 共过" +cnt + "人");  
    }  
    
    class PersonCrossBridge implements Runnable { // extends Thread {  
        private String personName;  
        private int direction;  
      
        public PersonCrossBridge(String personName, int direction) {  
            this.personName = personName;  
            this.direction = direction;  
        }  
      
        public void run() {  
            if (direction > 0) {  
                crossFromS2N(personName);  
            } else {  
                crossFromN2S(personName);  
            }  
        }  
    }  
}  

Java是面向对象,代码是简练了,但是你感觉这样设计类合适吗?
4 楼 wuyunbin 2011-05-13  
谢谢java_user, 如果代码使用inner class,似乎更简练:

class Bridge {
	private static final int TOTAL = 22;
	private int cnt = 0;
    public static void main(String[] args) {  
        Bridge bridge = new Bridge();  
        for (int i = 0; i < TOTAL; i++) {  
            if (i < 10) {  
                new Thread(bridge.new PersonCrossBridge("人" + i,  1) ).start();  
            } else {  
                new Thread(bridge.new PersonCrossBridge("人" + i,  -1)).start();  
            }  
        }  
    }  
    
    public synchronized void crossFromS2N(String person) {  
    	cnt++;
        System.out.print(person + "从南面开始");  
        try {  
            //模拟过桥  
            Thread.sleep(500);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        System.out.println("---到达北面, 共过" +cnt + "人");  
    }  
  
    public synchronized void crossFromN2S(String person) {  
    	cnt++;
        System.out.print(person + "从北面开始");
        try {  
            //模拟过桥  
            Thread.sleep(500);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        System.out.println("---到达南面, 共过" +cnt + "人");  
    }  
    
    class PersonCrossBridge implements Runnable { // extends Thread {  
        private String personName;  
        private int direction;  
      
        public PersonCrossBridge(String personName, int direction) {  
            this.personName = personName;  
            this.direction = direction;  
        }  
      
        public void run() {  
            if (direction > 0) {  
                crossFromS2N(personName);  
            } else {  
                crossFromN2S(personName);  
            }  
        }  
    }  
}  
3 楼 Technoboy 2011-05-12  

lz有点猛了...
http://technoboy.iteye.com/blog/1028828

相关推荐

Global site tag (gtag.js) - Google Analytics