java.util.concurrentパッケージは、並行プログラミングのための非常に強力なツールを提供します。
以下のコードでは、a を使用していますReentrantLock
(これは Java キーワードとよく似ておりsynchronized
、複数のスレッドが 1 つのコード ブロックに相互に排他的にアクセスできるようにします)。提供する他の優れた点ReentrantLock
は、続行する前に特定のイベントを待機Conditions
できることです。Threads
ここでは、RepaintManager
単純にループrepaint()
して、 を呼び出しますJPanel
。ただし、toggleRepaintMode()
が呼び出されるとブロックされ、再度呼び出されるmodeChanged Condition
まで待機します。toggleRepaintMode()
次のコードをすぐに実行できるはずです。JButton
のトグル再描画を押します(ステートメントJPanel
で動作することがわかります)。System.out.println
一般に、 java.util.concurrentが提供する機能に慣れることを強くお勧めします。非常に強力なものがたくさんあります。http://docs.oracle.com/javase/tutorial/essential/concurrency/に優れたチュートリアルがあります。
import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class RepaintTest {
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel()
{
@Override
public void paintComponent( Graphics g )
{
super.paintComponent( g );
// print something when the JPanel repaints
// so that we know things are working
System.out.println( "repainting" );
}
};
frame.add( panel );
final JButton button = new JButton("Button");
panel.add(button);
// create and start an instance of our custom
// RepaintThread, defined below
final RepaintThread thread = new RepaintThread( Collections.singletonList( panel ) );
thread.start();
// add an ActionListener to the JButton
// which turns on and off the RepaintThread
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
thread.toggleRepaintMode();
}
});
frame.setSize( 300, 300 );
frame.setVisible( true );
}
public static class RepaintThread extends Thread
{
ReentrantLock lock;
Condition modeChanged;
boolean repaintMode;
Collection<? extends Component> list;
public RepaintThread( Collection<? extends Component> list )
{
this.lock = new ReentrantLock( );
this.modeChanged = this.lock.newCondition();
this.repaintMode = false;
this.list = list;
}
@Override
public void run( )
{
while( true )
{
lock.lock();
try
{
// if repaintMode is false, wait until
// Condition.signal( ) is called
while ( !repaintMode )
try { modeChanged.await(); } catch (InterruptedException e) { }
}
finally
{
lock.unlock();
}
// call repaint on all the Components
// we're not on the event dispatch thread, but
// repaint() is safe to call from any thread
for ( Component c : list ) c.repaint();
// wait a bit
try { Thread.sleep( 50 ); } catch (InterruptedException e) { }
}
}
public void toggleRepaintMode( )
{
lock.lock();
try
{
// update the repaint mode and notify anyone
// awaiting on the Condition that repaintMode has changed
this.repaintMode = !this.repaintMode;
this.modeChanged.signalAll();
}
finally
{
lock.unlock();
}
}
}
}