Add project files

This commit is contained in:
Victor 2018-11-15 18:25:31 +02:00
commit 6e90036f08
21 changed files with 2346 additions and 0 deletions

73
build.xml Normal file
View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="Concurrency" default="default" basedir=".">
<description>Builds, tests, and runs the project Concurrency.</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar: JAR building
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="Concurrency-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
</project>

1419
nbproject/build-impl.xml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
build.xml.data.CRC32=6babcc3e
build.xml.script.CRC32=7a9b2ac7
build.xml.stylesheet.CRC32=8064a381@1.78.0.48
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=6babcc3e
nbproject/build-impl.xml.script.CRC32=2551e2ff
nbproject/build-impl.xml.stylesheet.CRC32=2b19b096@1.80.0.48

View File

View File

@ -0,0 +1,6 @@
compile.on.save=true
do.depend=false
do.jar=true
javac.debug=true
javadoc.preview=true
user.properties.file=C:\\Users\\aNNiMON\\AppData\\Roaming\\NetBeans\\dev\\build.properties

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group name="_TUTORIALS"/>
<group/>
</open-files>
</project-private>

View File

@ -0,0 +1,78 @@
annotation.processing.enabled=true
annotation.processing.enabled.in.editor=false
annotation.processing.processors.list=
annotation.processing.run.all.processors=true
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
application.title=Concurrency
application.vendor=aNNiMON
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
build.generated.sources.dir=${build.dir}/generated-sources
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
# Uncomment to specify the preferred debugger connection transport:
#debug.transport=dt_socket
debug.classpath=\
${run.classpath}
debug.test.classpath=\
${run.test.classpath}
# Files in build.classes.dir which should be excluded from distribution jar
dist.archive.excludes=
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/Concurrency.jar
dist.javadoc.dir=${dist.dir}/javadoc
endorsed.classpath=
excludes=
includes=**
jar.compress=false
javac.classpath=
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.external.vm=true
javac.processorpath=\
${javac.classpath}
javac.source=1.8
javac.target=1.8
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}:\
${libs.junit_4.classpath}:\
${libs.hamcrest.classpath}
javac.test.processorpath=\
${javac.test.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
main.class=concurrency.semaphore.SemaphoreDemo
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
mkdist.disabled=false
platform.active=default_platform
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project.
# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
# To set system properties for unit tests define test-sys-prop.name=value:
run.jvmargs=
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

15
nbproject/project.xml Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.java.j2seproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>Concurrency</name>
<source-roots>
<root id="src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
</data>
</configuration>
</project>

View File

@ -0,0 +1,37 @@
package concurrency.countdownlatch;
import java.util.concurrent.CountDownLatch;
// An example of CountDownLatch.
public final class CountDownLatchDemo {
public static void main(String args[]) {
CountDownLatch cdl = new CountDownLatch(5);
System.out.println("Starting");
new MyThread(cdl);
try {
cdl.await();
} catch (InterruptedException exc) {
System.out.println(exc);
}
System.out.println("Done");
}
static class MyThread implements Runnable {
CountDownLatch latch;
MyThread(CountDownLatch c) {
latch = c;
new Thread(this).start();
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(i);
latch.countDown(); // decrement count
}
}
}
}

View File

@ -0,0 +1,66 @@
package concurrency.countdownlatch;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
*
* @author aNNiMON
*/
public final class WaitToComplete {
public static void main(String[] args) throws InterruptedException {
// runInMainThread();
runInExecutor();
}
public static void runInMainThread() throws InterruptedException {
// final Executor executor = Runnable::run;
final Executor executor = new Executor() {
@Override
public void execute(final Runnable command) {
command.run();
}
};
final CountDownLatch latch = new CountDownLatch(2);
executor.execute(new FiniteThreadNamePrinterLatch(latch));
executor.execute(new FiniteThreadNamePrinterLatch(latch));
final boolean status = latch.await(5, TimeUnit.SECONDS);
System.out.println(status ? "Tasks successfully completed" : "Tasks does not complete, but that's all");
}
public static void runInExecutor() throws InterruptedException {
final ExecutorService executor = Executors.newCachedThreadPool();
final CountDownLatch latch = new CountDownLatch(2);
executor.execute(new FiniteThreadNamePrinterLatch(latch));
executor.execute(new FiniteThreadNamePrinterLatch(latch));
final boolean status = latch.await(5, TimeUnit.SECONDS);
System.out.println(status ? "Tasks successfully completed" : "Tasks does not complete, but that's all");
executor.shutdown();
}
private static class FiniteThreadNamePrinterLatch implements Runnable {
final CountDownLatch latch;
private FiniteThreadNamePrinterLatch(final CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
for (int i = 0; i < 25; i++) {
System.out.println("Run from thread: " + Thread.currentThread().getName());
try {
Thread.sleep(400);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
latch.countDown();
}
}
}

View File

@ -0,0 +1,59 @@
package concurrency.cyclicbarrier;
// An example of CyclicBarrier.
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public final class CyclicBarrierDemo {
public static void main(String args[]) {
// CyclicBarrier cb = new CyclicBarrier(3, new BarAction());
CyclicBarrier cb = new CyclicBarrier(3, () -> System.out.println("Barrier Reached!"));
System.out.println("Starting");
new MyThread(cb, "A");
new MyThread(cb, "B");
new MyThread(cb, "C");
// ++
new MyThread(cb, "X");
new MyThread(cb, "Y");
new MyThread(cb, "Z");
// ++
// for (char ch = 'A'; ch <= 'Z'; ch++) {
// new MyThread(cb, String.valueOf(ch));
// }
}
static class MyThread implements Runnable {
CyclicBarrier cbar;
String name;
MyThread(CyclicBarrier c, String n) {
cbar = c;
name = n;
new Thread(this).start();
}
@Override
public void run() {
System.out.println(name);
// for (int i = 0; i < 5; i++) {
// System.out.println(name + " " + i);
// }
try {
cbar.await();
} catch (BrokenBarrierException | InterruptedException exc) {
System.out.println(exc);
}
}
}
// An object of this class is called when the
// CyclicBarrier ends.
static class BarAction implements Runnable {
@Override
public void run() {
System.out.println("Barrier Reached!");
}
}
}

View File

@ -0,0 +1,67 @@
package concurrency.exchanger;
import java.util.concurrent.Exchanger;
// An example of Exchanger.
public final class ExchangerDemo {
public static void main(String args[]) {
Exchanger<String> exgr = new Exchanger<>();
new UseString(exgr);
new MakeString(exgr);
}
// A Thread that constructs a string.
static class MakeString implements Runnable {
Exchanger<String> ex;
String str;
MakeString(Exchanger<String> c) {
ex = c;
str = new String();
new Thread(this).start();
}
@Override
public void run() {
char ch = 'A';
for (int i = 0; i < 3; i++) { // !!! 3
// Fill Buffer
for (int j = 0; j < 5; j++) {
str += ch++;
}
try {
// Exchange a full buffer for an empty one.
str = ex.exchange(str);
} catch (InterruptedException exc) {
System.out.println(exc);
}
}
}
}
// A Thread that uses a string.
static class UseString implements Runnable {
Exchanger<String> ex;
String str;
UseString(Exchanger<String> c) {
ex = c;
new Thread(this).start();
}
@Override
public void run() {
for (int i = 0; i < 3; i++) { // !!! 3
try {
// Exchange an empty buffer for a full one.
str = ex.exchange(new String());
System.out.println("Got: " + str);
} catch (InterruptedException exc) {
System.out.println(exc);
}
}
}
}
}

View File

@ -0,0 +1,84 @@
package concurrency.executors;
import java.util.concurrent.*;
// An example that uses a Callable.
public final class CallableDemo {
public static void main(String args[]) {
ExecutorService es = Executors.newFixedThreadPool(3);
Future<Integer> f;
Future<Double> f2;
Future<Long> f3;
System.out.println("Starting");
f = es.submit(new Sum(10));
f2 = es.submit(new Hypot(3, 4));
f3 = es.submit(new Factorial(15));
// try {
// System.out.println(f.get());
// System.out.println(f2.get());
// System.out.println(f3.get());
// } catch (InterruptedException | ExecutionException exc) {
// System.out.println(exc);
// }
try {
System.out.println(f.get(10, TimeUnit.MILLISECONDS));
System.out.println(f2.get(10, TimeUnit.MILLISECONDS));
System.out.println(f3.get(10, TimeUnit.MILLISECONDS));
} catch (InterruptedException | ExecutionException | TimeoutException exc) {
System.out.println(exc);
}
es.shutdown();
System.out.println("Done");
}
// Following are three computational threads.
static class Sum implements Callable<Integer> {
int stop;
Sum(int v) {
stop = v;
}
@Override
public Integer call() {
int sum = 0;
for (int i = 1; i <= stop; i++) {
sum += i;
}
return sum;
}
}
static class Hypot implements Callable<Double> {
double side1, side2;
Hypot(double s1, double s2) {
side1 = s1;
side2 = s2;
}
@Override
public Double call() {
return Math.sqrt((side1 * side1) + (side2 * side2));
}
}
static class Factorial implements Callable<Long> {
int stop;
Factorial(int v) {
stop = v;
}
@Override
public Long call() {
long fact = 1;
for (int i = 2; i <= stop; i++) {
fact *= i;
}
return fact;
}
}
}

View File

@ -0,0 +1,50 @@
package concurrency.executors;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* @author aNNiMON
*/
public final class PiCalculatorDemo {
public static void main(String[] args) {
final ExecutorService executorService = Executors.newCachedThreadPool();
final long startTime = System.currentTimeMillis();
final Future<Double> future = executorService.submit(new PiCalculator());
try {
final double pi = future.get(10, TimeUnit.SECONDS);
final long stopTime = System.currentTimeMillis();
System.out.printf("Calculated Pi in %d milliseconds: %10.9f%n", stopTime - startTime, pi);
} catch (InterruptedException | ExecutionException | TimeoutException ex) {
ex.printStackTrace();
executorService.submit(() -> System.exit(0));
} finally {
executorService.shutdown();
}
}
private static class PiCalculator implements Callable<Double> {
@Override
public Double call() throws Exception {
double currVal = 1.0;
double nextVal = 0.0;
double denominator = 1.0;
for (int i = 0; Math.abs(nextVal - currVal) > 0.000000001d; denominator += 2.0, i++) {
currVal = nextVal;
if (i % 2 == 1) {
nextVal = currVal - (1 / denominator);
} else {
nextVal = currVal + (1 / denominator);
}
}
return currVal * 4;
}
}
}

View File

@ -0,0 +1,50 @@
package concurrency.executors;
import java.util.concurrent.*;
// A simple example that uses an Executor.
public final class SimpleExecutorDemo {
public static void main(String args[]) {
CountDownLatch cdl = new CountDownLatch(5);
CountDownLatch cdl2 = new CountDownLatch(5);
CountDownLatch cdl3 = new CountDownLatch(5);
CountDownLatch cdl4 = new CountDownLatch(5);
ExecutorService es = Executors.newFixedThreadPool(2);
System.out.println("Starting");
// Start the threads.
es.execute(new MyThread(cdl, "A"));
es.execute(new MyThread(cdl2, "B"));
es.execute(new MyThread(cdl3, "C"));
es.execute(new MyThread(cdl4, "D"));
try {
cdl.await();
cdl2.await();
cdl3.await();
cdl4.await();
} catch (InterruptedException exc) {
System.out.println(exc);
}
es.shutdown();
System.out.println("Done");
}
static class MyThread implements Runnable {
String name;
CountDownLatch latch;
MyThread(CountDownLatch c, String n) {
latch = c;
name = n;
new Thread(this);
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(name + ": " + i);
latch.countDown();
}
}
}
}

View File

@ -0,0 +1,68 @@
package concurrency.phaser;
// An example of Phaser.
import java.util.concurrent.*;
public final class PhaserDemo {
public static void main(String args[]) {
Phaser phsr = new Phaser(1);
int curPhase;
System.out.println("Starting");
new MyThread(phsr, "A");
new MyThread(phsr, "B");
new MyThread(phsr, "C");
// Wait for all threads to complete phase one.
curPhase = phsr.getPhase();
phsr.arriveAndAwaitAdvance();
System.out.println("Phase " + curPhase + " Complete");
// Wait for all threads to complete phase two.
curPhase = phsr.getPhase();
phsr.arriveAndAwaitAdvance();
System.out.println("Phase " + curPhase + " Complete");
curPhase = phsr.getPhase();
phsr.arriveAndAwaitAdvance();
System.out.println("Phase " + curPhase + " Complete");
// Deregister the main thread.
phsr.arriveAndDeregister();
if (phsr.isTerminated())
System.out.println("The Phaser is terminated");
}
}
// A thread of execution that uses a Phaser.
class MyThread implements Runnable {
Phaser phsr;
String name;
MyThread(Phaser p, String n) {
phsr = p;
name = n;
phsr.register(); // !!!
new Thread(this).start();
}
@Override
public void run() {
System.out.println("Thread " + name + " Beginning Phase One");
phsr.arriveAndAwaitAdvance(); // Signal arrival.
// Pause a bit to prevent jumbled output. This is for illustration
// only. It is not required for the proper operation of the phaser.
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println(e);
}
System.out.println("Thread " + name + " Beginning Phase Two");
phsr.arriveAndAwaitAdvance(); // Signal arrival.
// Pause a bit to prevent jumbled output. This is for illustration
// only. It is not required for the proper operation of the phaser.
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println(e);
}
System.out.println("Thread " + name + " Beginning Phase Three");
phsr.arriveAndDeregister(); // Signal arrival and deregister.
}
}

View File

@ -0,0 +1,77 @@
package concurrency.phaser;
import java.util.concurrent.Phaser;
/**
*
* @author aNNiMON
*/
public final class PhaserDemo2 {
public static void main(String args[]) {
MyPhaser phsr = new MyPhaser(1, 4);
System.out.println("Starting\n");
new MyThread2(phsr, "A");
new MyThread2(phsr, "B");
new MyThread2(phsr, "C");
// Wait for the specified number of phases to complete.
while (!phsr.isTerminated()) {
phsr.arriveAndAwaitAdvance();
}
System.out.println("The Phaser is terminated");
}
}
// A thread of execution that uses a Phaser.
class MyThread2 implements Runnable {
Phaser phsr;
String name;
MyThread2(Phaser p, String n) {
phsr = p;
name = n;
phsr.register();
new Thread(this).start();
}
@Override
public void run() {
while (!phsr.isTerminated()) {
System.out.println("Thread " + name + " Beginning Phase " + phsr.getPhase());
phsr.arriveAndAwaitAdvance();
// Pause a bit to prevent jumbled output. This is for illustration
// only. It is not required for the proper operation of the phaser.
try {
Thread.sleep(10);
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
}
// Extend MyPhaser to allow only a specific number of phases
// to be executed.
class MyPhaser extends Phaser {
int numPhases;
MyPhaser(int parties, int phaseCount) {
super(parties);
numPhases = phaseCount - 1;
}
// Override onAdvance() to execute the specified
// number of phases.
@Override
protected boolean onAdvance(int p, int regParties) {
// This println() statement is for illustration only.
// Normally, onAdvance() will not display output.
System.out.println("Phase " + p + " completed.\n");
// If all phases have completed, return true
if (p == numPhases || regParties == 0)
return true;
// Otherwise, return false.
return false;
}
}

View File

@ -0,0 +1,39 @@
package concurrency.semaphore;
import java.util.concurrent.Semaphore;
// A thread of execution that decrements count.
public final class DecrementThread implements Runnable {
String name;
Semaphore sem;
DecrementThread(Semaphore s, String n) {
sem = s;
name = n;
new Thread(this).start();
}
@Override
public void run() {
System.out.println("Starting " + name);
try {
// First, get a permit.
System.out.println(name + " is waiting for a permit.");
sem.acquire();
System.out.println(name + " gets a permit.");
// Now, access shared resource.
for (int i = 0; i < 5; i++) {
Shared.count--;
System.out.println(name + ": " + Shared.count);
// Now, allow a context switch -- if possible.
Thread.sleep(10);
}
} catch (InterruptedException exc) {
System.out.println(exc);
}
// Release the permit.
System.out.println(name + " releases the permit.");
sem.release();
}
}

View File

@ -0,0 +1,39 @@
package concurrency.semaphore;
import java.util.concurrent.Semaphore;
// A thread of execution that increments count.
public final class IncrementThread implements Runnable {
String name;
Semaphore sem;
IncrementThread(Semaphore s, String n) {
sem = s;
name = n;
new Thread(this).start();
}
@Override
public void run() {
System.out.println("Starting " + name);
try {
// First, get a permit.
System.out.println(name + " is waiting for a permit.");
sem.acquire();
System.out.println(name + " gets a permit.");
// Now, access shared resource.
for (int i = 0; i < 5; i++) {
Shared.count++;
System.out.println(name + ": " + Shared.count);
// Now, allow a context switch -- if possible.
Thread.sleep(10);
}
} catch (InterruptedException exc) {
System.out.println(exc);
}
// Release the permit.
System.out.println(name + " releases the permit.");
sem.release();
}
}

View File

@ -0,0 +1,82 @@
package concurrency.semaphore;
import java.util.concurrent.Semaphore;
// An implementation of a producer and consumer
// that use semaphores to control synchronization.
public final class ProducerConsumerDemo {
public static void main(String args[]) {
new ProducerConsumerDemo();
}
public ProducerConsumerDemo() {
Q q = new Q();
new Consumer(q);
new Producer(q);
}
static class Q {
int n;
// Start with consumer semaphore unavailable.
static Semaphore semCon = new Semaphore(0);
static Semaphore semProd = new Semaphore(1);
void get() {
try {
// System.out.println(Thread.currentThread().getName() + " is waiting for a permit in get");
semCon.acquire();
// System.out.println(Thread.currentThread().getName() + " gets a permit in get.");
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
System.out.println("Got: " + n);
semProd.release();
}
void put(int n) {
try {
// System.out.println(Thread.currentThread().getName() + " is waiting for a permit in put");
semProd.acquire();
// System.out.println(Thread.currentThread().getName() + " gets a permit in put.");
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
this.n = n;
System.out.println("Put: " + n);
semCon.release();
}
}
class Producer implements Runnable {
Q q;
Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
q.put(i);
}
}
}
class Consumer implements Runnable {
Q q;
Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
q.get();
}
}
}
}

View File

@ -0,0 +1,21 @@
package concurrency.semaphore;
import java.util.concurrent.Semaphore;
/**
*
* @author aNNiMON
*/
public final class SemaphoreDemo {
public static void main(String[] args) {
Semaphore sem = new Semaphore(1);
new IncrementThread(sem, "A");
new DecrementThread(sem, "B");
}
}
// A shared resource.
class Shared {
static int count = 0;
}