所以大家好,我实际上是新编码的,即使是基本编码也存在很多问题。
所以我的讲师给出了这个案例研究:模拟一次可以容纳1架飞机降落的飞机和4条跑道的数量。如果所有4条跑道都被占用,其他飞机必须等待其中一条或多条跑道起飞。对我来说很难,所以我首先尝试使用2条跑道和4架飞机。
Plane是线程类,Runway是普通类。到目前为止我做了什么:
主类
public class Main {
public static void main(String[] args) {
Runway r[] = new Runway[2];
for (int i = 0; i < r.length; i++) {
r[i] = new Runway(i);
}
Plane p[] = new Plane[4];
for (int i = 0; i < p.length; i++){
p[i] = new Plane(i, r[0], r[1]);
p[i].start();
}
}
}
跑道班
public class Runway {
private int id;
private Lock l;
public boolean available = true;
public Runway(int id){
this.id = id;
l = new ReentrantLock();
}
public boolean landing(int idp){
boolean i;
i = l.tryLock();
if (i == true) {
available = false;
System.out.println("Plane " + idp + " is landing on Runway: " + id);
}
return i;
}
public void takeOff(int idp){
System.out.println("Plane " + idp + " is take off from Runway: " + id);
available = true;
l.unlock();
}
}
平面类
public class Plane extends Thread {
private Runway r1, r2;
private int id, tag;
private boolean i = false;
public Plane(int id, Runway r1, Runway r2){
this.id = id;
this.r1 = r1;
this.r2 = r2;
}
public void run(){
if (i == false) {
if (r1.available == true) {
i = r1.landing(id);
tag = 1;
} else if (r2.available == true) {
i = r2.landing(id);
tag = 2;
}
}
sleep();
if (tag == 1 & i == true){
r1.takeOff(id);
i = false;
} else if (tag == 2 & i == true) {
r2.takeOff(id);
i = false;
}
}
private void sleep(){
try {
Thread.sleep(new Random().nextInt(8)*100);
}catch (Exception e){}
}
}
这是结果......
Plane 1 is landing on Runway: 0
Plane 3 is landing on Runway: 1
Plane 1 is take off from Runway: 0
Plane 3 is take off from Runway: 1
Process finished with exit code 0
并非所有飞机都着陆,我知道这是基本的,但任何帮助都表示赞赏:D
答案 0 :(得分:0)
这是一种替代同步访问共享状态的方法。将变量标记为易失性是一个简单的&#39;替代同步,具有较少的运行时开销。它告诉JVM内存管理器保证&#39;活跃度&#39;变量到所有访问线程
修改
import java.util。*; import java.util.concurrent.atomic.AtomicReference;
public class Airport {
/**
* if number of planes is less than or equal to twice the number of runways
* the execution will terminate ie all planes that want to land
* will land and all those that wish to take off will take off .
* Otherwise there wont be enough runways for the landing planes and the execution will
* go on indefinitely .
*/
static Runway r[] = new Runway[10];
static Plane p[] = new Plane[20];
public static void main(String[] args) {
//instantiate array of planes
for (int i = 0; i < p.length; i++){
p[i] = new Plane(i);
}
//instantiate runways and allocate planes to runways
List<Plane> planes = Arrays.asList(p);
Iterator<Plane> iterator;
Collections.shuffle(planes);
iterator= planes.iterator();
for (int i = 0; i < r.length; i++) {
Plane p;
try {
p= iterator.next();
}catch ( RuntimeException e){
p= null;
}
r[i] = new Runway(i,p);
}
//display initial state
for (int i = 0; i < p.length; i++){
Runway runway=getUsedRunway(p[i]);
System.out.println("plane "+p[i].id + " is "+(runway==null?"waiting to land":("on runway "+runway.id)));
}
System.out.println("======== Begin! ============");
//let the games begin
for (int i = 0; i < p.length; i++){
p[i].start();
}
}
private static class Runway {
//only ever read after construction . no need for special handling for concurreny
private int id;
/**
* volatile keyword gives atomic read and atomic write operation in isolation .
* However to land the plane we need to set the runway's plane reference value based on its current value .
* This scenario is called out specifically by B Goetz in this article https://www.ibm.com/developerworks/java/library/j-jtp06197/
* ( and in his book Javas one in which volatile is insufficient for thread safety
* We need an atomic compare and set
*/
private AtomicReference<Plane> planeAtomicReference;
public Runway(int i, Plane p) {
id =i;
planeAtomicReference = new AtomicReference<>();
planeAtomicReference.set(p);
}
}
private static class Plane extends Thread {
//only ever read after construction . no need for special handling for concurreny
private int id;
Plane(int i){
id=i;
}
@Override
public void run() {
Runway runway=getUsedRunway(this);
if(runway==null){
System.out.println("plane "+id+" wants to land");
Runway availableRunway = getAvailableRunway();
while ((availableRunway=atomicallyAttempToLandPlane(this))==null) {
System.out.println("no runway available yet for plane " + id);
try {
sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("landed plane "+id+" on runway "+availableRunway.id);
}else {
System.out.println("plane "+id+" wants to take off from runway "+runway.id);
runway.planeAtomicReference.set(null);
System.out.println("plane "+id+" has taken off from runway ");
}
}
/**
*
* @param plane
* @return
*/
private Runway atomicallyAttempToLandPlane(Plane plane) {
for (int i = 0; i < r.length; i++) {
if(r[i].planeAtomicReference.compareAndSet(null,plane)){
return r[i];
}
}
return null;
}
}
/**
* does not require synchronization since the size of the arrays is fixed during execution and the elements
* to which they refer is also fixed . only the internal state of elements themselves is open to change
* and that has been guaranteed by marking it as volatile as well as additional atomic behaviour
* @return
*/
private static Runway getAvailableRunway(){
for (int i = 0; i < r.length; i++) {
if(r[i].planeAtomicReference.get() ==null){
return r[i];
}
}
return null;
}
/**
* does not require synchronization since the size of the arrays is fixed during execution and the elements
* to which they refer is also fixed . only the internal state of elements themselves is open to change
* and that has been guaranteed by marking it as volatile as well as additional atomic behaviour
* @param plane
* @return
*/
private static Runway getUsedRunway(Plane plane){
for (int i = 0; i < r.length; i++) {
final Plane planeOnRunway = r[i].planeAtomicReference.get();
if(planeOnRunway !=null && planeOnRunway.id==plane.id){
return r[i];
}
}
return null;
}
}
答案 1 :(得分:0)
通过将飞机视为线程,将跑道数视为信号灯中的锁数来解决此问题。
然后代码将如下所示:
public class Runway {
Semaphore semaphore = new Semaphore(4);
public void landThePlane() {
try {
semaphore.acquire();
// code to land the plane
System.out.println("The plane is landing");
Thread.sleep(3000); // just to show you in the console that the next 4
// threads will be executed afterwards - not imp
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Runway runway = new Runway();
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
executorService.execute(() -> runway.landThePlane());
}
}
}