public interface Runnable
{
void run();
}public class MyRunnable implements Runnable
{
public void run()
{
// Task statements go here
. . .
}
}Runnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
A program to print a time stamp and "Hello World" once a second for ten seconds:
Thu Dec 28 23:12:03 PST 2004 Hello, World! Thu Dec 28 23:12:04 PST 2004 Hello, World! Thu Dec 28 23:12:05 PST 2004 Hello, World! Thu Dec 28 23:12:06 PST 2004 Hello, World! Thu Dec 28 23:12:07 PST 2004 Hello, World! Thu Dec 28 23:12:08 PST 2004 Hello, World! Thu Dec 28 23:12:09 PST 2004 Hello, World! Thu Dec 28 23:12:10 PST 2004 Hello, World! Thu Dec 28 23:12:11 PST 2004 Hello, World! Thu Dec 28 23:12:12 PST 2004 Hello, World!
public class GreetingRunnable implements Runnable
{
public GreetingRunnable(String aGreeting)
{
greeting = aGreeting;
}
public void run()
{
// Task statements go here
. . .
}
// Fields used by the task statements
private String greeting;
}
Thread.sleep(milliseconds)
public void run()
{
try
{
Task statements
}
catch (InterruptedException exception)
{
}
Clean up, if necessary
}
Runnable t = new GreetingRunnable("Hello World");Thread t = new Thread(r); t.start();
Thu Dec 28 23:12:03 PST 2004 Hello, World! Thu Dec 28 23:12:03 PST 2004 Goodbye, World! Thu Dec 28 23:12:04 PST 2004 Hello, World! Thu Dec 28 23:12:05 PST 2004 Hello, World! Thu Dec 28 23:12:04 PST 2004 Goodbye, World! Thu Dec 28 23:12:05 PST 2004 Goodbye, World! Thu Dec 28 23:12:06 PST 2004 Hello, World! Thu Dec 28 23:12:06 PST 2004 Goodbye, World! Thu Dec 28 23:12:07 PST 2004 Hello, World! Thu Dec 28 23:12:07 PST 2004 Goodbye, World! Thu Dec 28 23:12:08 PST 2004 Hello, World! Thu Dec 28 23:12:08 PST 2004 Goodbye, World! Thu Dec 28 23:12:09 PST 2004 Hello, World! Thu Dec 28 23:12:09 PST 2004 Goodbye, World! Thu Dec 28 23:12:10 PST 2004 Hello, World! Thu Dec 28 23:12:10 PST 2004 Goodbye, World! Thu Dec 28 23:12:11 PST 2004 Goodbye, World! Thu Dec 28 23:12:11 PST 2004 Hello, World! Thu Dec 28 23:12:12 PST 2004 Goodbye, World! Thu Dec 28 23:12:12 PST 2004 Hello, World!
r1.run(); r2.run();instead of starting threads?
t.interrupt();
public void run()
{
for (int i = 1;
i <= REPETITIONS && !Thread.interrupted(); i++)
{
Do work
}
Clean up
}public void run()
{
try
{
for (int i = 1; i <= REPETITIONS; i++)
{
Do work
}
}
catch (InterruptedException exception)
{
}
Clean up
}public class MyRunnable implements Runnable
{
public void run()
{
try
{
System.out.println(1);
Thread.sleep(1000);
System.out.println(2);
}
catch (InterruptedException exception)
{
System.out.println(3);
}
System.out.println(4);
}
}
Suppose a thread with this runnable is started and immediately interrupted.
Thread t = new Thread(new MyRunnable()); t.start(); t.interrupt();What output is produced?
public void run()
{
try
{
for (int i = 1; i <= count; i++)
{
account.deposit(amount);
Thread.sleep(DELAY);
}
}
catch (InterruptedException exception)
{
}
}public void deposit(double amount)
{
System.out.print("Depositing " + amount);
double newBalance = balance + amount;
System.out.println(", new balance is " + newBalance);
balance = newBalance;
}Depositing 100.0, new balance is 100.0 Withdrawing 100.0, new balance is 0.0 Depositing 100.0, new balance is 100.0 Depositing 100.0, new balance is 200.0 Withdrawing 100.0, new balance is 100.0 . . . Withdrawing 100.0, new balance is 0.0
Depositing 100.0Withdrawing 100.0, new balance is 100.0, new balance is -100.0
System.out.print("Depositing " + amount);
double newBalance = balance + amount;
The balance field is still 0, and the newBalance local variable is 100
System.out.println(", new balance is " + newBalance);
balance = newBalance;
The balance is now 100 instead of 0 because the deposit method used the
OLD balance
public void deposit(double amount)
{
balance = balance + amount;
System.out.print("Depositing " + amount + ", new balance is " + balance);
}
Race condition can still occur:
balance = the right-hand-side value
Depositing 100.0, new balance is 100.0 Withdrawing 100.0, new balance is 0.0 Depositing 100.0, new balance is 100.0 Withdrawing 100.0, new balance is 0.0 . . . Withdrawing 100.0, new balance is 400.0 Depositing 100.0, new balance is 500.0 Withdrawing 100.0, new balance is 400.0 Withdrawing 100.0, new balance is 300.0
public class BankAccount
{
public BankAccount()
{
balanceChangeLock = new ReentrantLock();
. . .
}
. . .
private Lock balanceChangeLock;
}
balanceChangeLock.lock(); Code that manipulates the shared resource balanceChangeLock.unlock();
public void deposit(double amount)
{
balanceChangeLock.lock();
try
{
System.out.print("Depositing " + amount);
double newBalance = balance + amount;
System.out.println(", new balance is " + newBalance);
balance = newBalance;
}
finally
{
balanceChangeLock.unlock();
}
}
public void withdraw(double amount)
{
balanceChangeLock.lock();
try
{
while (balance < amount)
Wait for the balance to grow
. . .
}
finally
{
balanceChangeLock.unlock();
}
}
public class BankAccount
{
public BankAccount()
{
balanceChangeLock = new ReentrantLock();
sufficientFundsCondition = balanceChangeLock.newCondition();
. . .
}
. . .
private Lock balanceChangeLock;
private Condition sufficientFundsCondition;
}public void withdraw(double amount)
{
balanceChangeLock.lock();
try
{
while (balance < amount)
sufficientFundsCondition.await();
. . .
}
finally
{
balanceChangeLock.unlock();
}
}sufficientFundsCondition.signalAll();
Depositing 100.0, new balance is 100.0 Withdrawing 100.0, new balance is 0.0 Depositing 100.0, new balance is 100.0 Depositing 100.0, new balance is 200.0 . . . Withdrawing 100.0, new balance is 100.0 Depositing 100.0, new balance is 200.0 Withdrawing 100.0, new balance is 100.0 Withdrawing 100.0, new balance is 0.0
public class SelectionSorter
{
public SelectionSorter(int[] anArray, JComponent aComponent)
{
a = anArray;
sortStateLock = new ReentrantLock();
component = aComponent;
}
. . .
private JComponent component;
}
public void pause(int steps)
throws InterruptedException
{
component.repaint();
Thread.sleep(steps * DELAY);
}public void draw(Graphics2D g2)
{
sortStateLock.lock();
try
{
int deltaX = component.getWidth() / a.length;
for (int i = 0; i < a.length; i++)
{
if (i == markedPosition)
g2.setColor(Color.RED);
else if (i <= alreadySorted)
g2.setColor(Color.BLUE);
else
g2.setColor(Color.BLACK);
g2.draw(new Line2D.Double(i * deltaX, 0, i * deltaX, a[i]));
}
}
finally
{
sortStateLock.unlock();
}
}
public int minimumPosition(int from)
throws InterruptedException
{
int minPos = from;
for (int i = from + 1; i < a.length; i++)
{
sortStateLock.lock();
try
{
if (a[i] < a[minPos]) minPos = i;
markedPosition = i;
}
finally
{
sortStateLock.unlock();
}
pause(2); // two array elements were inspected
}
return minPos;
}
public class SelectionSortComponent extends JComponent
{
public void paintComponent(Graphics g)
{
if (sorter == null) return;
Graphics2D g2 = (Graphics2D) g;
sorter.draw(g2);
}
. . .
private SelectionSorter sorter;
}
public void startAnimation()
{
int[] values = ArrayUtil.randomIntArray(30, 300);
sorter = new SelectionSorter(values, this);
class AnimationRunnable implements Runnable
{
public void run()
{
try
{
sorter.sort();
}
catch (InterruptedException exception)
{
}
}
}
Runnable r = new AnimationRunnable();
Thread t = new Thread(r);
t.start();
}