スレッドの開始・停止・再開 -- およびActionインタフェース
戻る
::::::::::::::
Cell.java
::::::::::::::
/**
$Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
@author KISHI Yasuhiro
*/
public class Cell {
/** サブクラスからのアクセスを許可する */
protected int x;
protected int y;
public Cell( int x, int y ) {
this.x = x;
this.y = y;
}
/** 次の位置に移動する */
public void moveNext( int x, int y ) {
this.x = x;
this.y = y;
}
public void follow( Cell cell ) {
this.x = cell.getX();
this.y = cell.getY();
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
::::::::::::::
CellList.java
::::::::::::::
import java.util.*;
/**
* <pre>
* $Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
* @author KISHI Yasuhiro
* セルを結合したクラス
* </pre>
*/
public class CellList extends LinkedList implements Runnable {
private int xMax;
private int yMax;
/** 格納するセルの最大個数 */
private int maxSize = 10;
public CellList() {
super();
}
public void setBoundary( int x, int y ) {
this.xMax = x;
this.yMax = y;
}
/** スレッドを開始する */
public void start() {
( new Thread( this ) ).start();
}
public void run() {
while ( true ) {
// 移動する
move();
// 増殖する
multiply();
try {
Thread.sleep( 200 );
} catch ( Exception exception ) {
exception.printStackTrace();
}
}
}
private synchronized void multiply() {
// 末尾のセルを求める
Cell tailCell = ( Cell ) this.getLast();
int currentX = tailCell.getX();
int currentY = tailCell.getY();
int nextX;
int nextY;
if ( this.size() < maxSize ) {
nextX = currentX;
nextY = currentY;
Random random = new Random();
int position = Math.abs( random.nextInt() % 4 );
switch ( position ) {
case 0:
// 右に追加
nextX++;
break;
case 1:
// 下に追加
nextY++;
break;
case 2:
// 左に追加
nextX--;
break;
case 3:
// 上に追加
nextY--;
break;
default:
// Do nothing
break;
}
this.add( new Cell( nextX, nextY ) );
}
}
private void move() {
Cell headCell = ( Cell ) this.getFirst();
int currentX = headCell.getX();
int currentY = headCell.getY();
int nextX;
int nextY;
do {
nextX = currentX;
nextY = currentY;
// 次の移動位置をランダムに与える
Random random = new Random();
int direction = Math.abs( random.nextInt() % 4 );
switch ( direction ) {
case 0:
// 右に移動
nextX++;
break;
case 1:
// 下に移動
nextY++;
break;
case 2:
// 左に移動
nextX--;
break;
case 3:
// 上に移動
nextY--;
break;
default:
// Do nothing
break;
}
if ( isOccupied( nextY, nextY ) ) {
// 他のセルと同じ場所であれば、そこには進まない
continue;
}
} while ( isOutOfBoundary( nextX, nextY ) );
headCell.moveNext( nextX, nextY );
// DEBUG
// System.out.printf( "%3d : %3d\n", headCell.getX(), headCell.getY() );
/** 先頭のセルに追従する */
Cell newCell = new Cell( currentX, currentY ); // 先頭セルの移動前の位置
for ( int i = 1;i < this.size();i++ ) {
Cell targetCell = ( Cell ) this.get( i );
// 現在の位置を保持しておく→後続のセルの移動先
int x = targetCell.getX();
int y = targetCell.getY();
// 新しい位置に移動
targetCell.follow( newCell );
newCell = new Cell( x, y );
}
}
/** 他のセルが既にその位置を占有しているかどうか */
private boolean isOccupied( int x, int y ) {
boolean occupied = false;
Iterator iterator = this.iterator();
while ( iterator.hasNext() ) {
Cell cell = ( Cell ) iterator.next();
if ( cell.getX() == x && cell.getY() == y ) {
occupied = true;
break;
}
}
return occupied;
}
/** 境界をはみ出したかどうか */
private boolean isOutOfBoundary( int x, int y ) {
return ( x < 0 || x > xMax || y < 0 || y > yMax );
}
static public void main( String[] args ) {
CellList list = new CellList();
list.setBoundary( 10, 10 );
list.add( new Cell( 0, 0 ) );
list.start();
}
}
::::::::::::::
CellPainter.java
::::::::::::::
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
/**
$Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
@author KISHI Yasuhiro
*/
public class CellPainter {
static public synchronized void paint( Graphics g, CellList cellList ) {
Iterator iterator = cellList.iterator();
int i = 0;
while ( iterator.hasNext() ) {
Cell cell = ( Cell ) iterator.next();
int x = cell.getX();
int y = cell.getY();
if ( i == 0 ) {
g.setColor( Color.red );
} else {
g.setColor( Color.yellow );
}
g.fillOval( GridPainter.PITCH * x, GridPainter.PITCH * y, GridPainter.PITCH, GridPainter.PITCH );
i++;
}
}
}
::::::::::::::
Cellula.java
::::::::::::::
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
$Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
@author KISHI Yasuhiro
*/
public class Cellula extends Cell implements Runnable {
private int xMax;
private int yMax;
CellulaManager manager;
public Cellula( int x, int y, int xMax, int yMax, CellulaManager manager ) {
super( x, y );
this.xMax = xMax;
this.yMax = yMax;
this.manager = manager;
manager.add( this );
( new Thread( this ) ).start();
}
/** 境界をはみ出したかどうか */
private boolean isOutOfBoundary( int x, int y ) {
return ( x < 0 || x > xMax || y < 0 || y > yMax );
}
public void run() {
while ( true ) {
migrate();
beget();
try {
Thread.sleep( 100 );
} catch ( Exception e ) {
e.printStackTrace();
}
}
}
/** 増殖させる */
private void beget() {
if ( !manager.isAcceptable() ) {
return ;
}
Cellula cellula = new Cellula( x, y, xMax, yMax, manager );
}
private void migrate() {
int currentX = this.getX();
int currentY = this.getY();
int nextX;
int nextY;
do {
nextX = currentX;
nextY = currentY;
// 次の移動位置をランダムに与える
Random random = new Random();
int direction = Math.abs( random.nextInt() % 4 );
switch ( direction ) {
case 0:
// 右に移動
nextX++;
break;
case 1:
// 下に移動
nextY++;
break;
case 2:
// 左に移動
nextX--;
break;
case 3:
// 上に移動
nextY--;
break;
default:
// Do nothing
break;
}
} while ( isOutOfBoundary( nextX, nextY ) );
// DEBUG
// System.out.println(nextX + ":" + nextY);
moveNext( nextX, nextY );
}
public void paint( Graphics g ) {
g.setColor( Color.red );
g.fillOval( GridPainter.PITCH * x, GridPainter.PITCH * y, GridPainter.PITCH, GridPainter.PITCH );
}
}
::::::::::::::
CellulaManager.java
::::::::::::::
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
$Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
@author KISHI Yasuhiro
*/
public class CellulaManager {
/** 許容最大数 */
private int permissibleCount;
java.util.List list;
public CellulaManager( int permissibleCount ) {
list = new LinkedList();
this.permissibleCount = permissibleCount;
}
public void add
( Cellula cellula ) {
list.add( cellula );
}
public synchronized boolean isAcceptable() {
return permissibleCount > list.size();
}
public synchronized void paintAll( Graphics g ) {
Iterator iterator = list.iterator();
while ( iterator.hasNext() ) {
Cellula cellula = ( Cellula ) iterator.next();
cellula.paint( g );
}
}
}
::::::::::::::
CommandPanel.java
::::::::::::::
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
$Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
@author KISHI Yasuhiro
*/
public class CommandPanel extends JPanel {
private JButton startButton, stopButton;
private JLabel counterLabel;
public CommandPanel( DrawingPanel dp ) {
startButton = new JButton( "START" );
stopButton = new JButton( "STOP" );
counterLabel = new JLabel();
this.add( startButton );
this.add( stopButton );
this.add( counterLabel );
//-----------------------------------------------------
// アクションリスナーの追加
//-----------------------------------------------------
Action action = new CommandPanelAction ( dp );
startButton.setActionCommand( "START" );
startButton.addActionListener( action );
stopButton.setActionCommand( "STOP" );
stopButton.addActionListener( action );
}
public JLabel getCounterLabel() {
return this.counterLabel;
}
}
::::::::::::::
CommandPanelAction.java
::::::::::::::
import javax.swing.*;
import java.awt.event.*;
import java.net.*;
/**
* <pre>
* $Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
* @author KISHI Yasuhiro
* コマンドパネル上でのアクションを制御するクラス
* </pre>
*/
public class CommandPanelAction extends AbstractAction {
private DrawingPanel dp;
public CommandPanelAction( DrawingPanel dp ) {
this.dp = dp;
}
public synchronized void actionPerformed( ActionEvent e ) {
String actionCommand = e.getActionCommand();
if ( "START".equals( actionCommand ) ) {
System.out.println( "STARTがクリックされました!" );
dp.setRunningStatus( true );
} else if ( "STOP".equals( actionCommand ) ) {
System.out.println( "STOPがクリックされました!" );
dp.setRunningStatus( false );
}
}
}
::::::::::::::
DrawingPanel.java
::::::::::::::
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
$Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
@author KISHI Yasuhiro
*/
public class DrawingPanel extends JPanel implements Runnable {
private long counter = 0;
private JLabel counterLabel;
private boolean runningStatus;
private Thread thread;
private CellList cellList;
private CellulaManager cellulaManager;
private Cellula cellula;
public DrawingPanel() {
// セルリスト
cellList = new CellList();
cellList.setBoundary( 80, 60 );
cellList.add( new Cell( 40, 30 ) );
cellList.start();
// Cellula
cellulaManager = new CellulaManager( 360 );
cellula = new Cellula( 30, 30, 80, 60, cellulaManager );
//---------------------------------------------------
// スレッド開始
//---------------------------------------------------
runningStatus = true;
thread = new Thread( this );
thread.start();
}
/** カウンターラベルの参照を引き渡す */
public void setReference( JLabel counterLabel ) {
this.counterLabel = counterLabel;
}
/** 稼動・停止の状態を変更する */
public synchronized void setRunningStatus( boolean status ) {
this.runningStatus = status;
System.out.println( "runningStatus = " + runningStatus );
if ( runningStatus == false && thread != null ) {
// スレッドのインスタンスを消滅させる必要あり
thread = null;
}
if ( runningStatus == true && thread == null ) {
// 一度run()メソッドが完了したら再度スタートさせなければいけない
thread = new Thread( this );
thread.start();
}
}
public void run() {
while ( runningStatus ) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
repaint();
}
}
);
try {
Thread.sleep( 100 );
} catch ( Exception e ) {
e.printStackTrace();
}
counter++;
if ( counter % 100 == 0 ) {
System.out.println( counter );
}
//-----------------------------------------------------
// コマンドパネル内のカウンターラベルの値を更新
//-----------------------------------------------------
counterLabel.setText( String.valueOf( counter ) );
}
}
public void clearScreen( Graphics g ) {
int width = getWidth();
int height = getHeight();
//--------------------------------------------------
// 画面クリア
//--------------------------------------------------
g.setColor( Color.black );
g.fillRect( 0 , 0 , width , height );
}
public void paintComponent( Graphics g ) {
int width = getWidth();
int height = getHeight();
clearScreen( g );
// 格子を描画
GridPainter.paint( g, width, height );
// セルリストを描画
CellPainter.paint( g, cellList );
// Cellula
cellulaManager.paintAll( g );
}
}
::::::::::::::
GridPainter.java
::::::::::::::
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
$Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
@author KISHI Yasuhiro
*/
public class GridPainter {
static public final int PITCH = 10;
static public void paint( Graphics g, int width, int height ) {
g.setColor( Color.blue );
for ( int x = 0;x < width;x += PITCH ) {
g.drawLine( x, 0, x, height );
}
for ( int y = 0;y < height;y += PITCH ) {
g.drawLine( 0, y, width, y );
}
}
}
::::::::::::::
StruggleForSurvival.java
::::::::::::::
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
* <pre>
* 生存競争をシミュレーションするApplet
* </pre>
* $Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
* @author KISHI Yasuhiro
*/
public class StruggleForSurvival extends JApplet {
public void init() {
Container contentPane = getContentPane();
System.out.println( getWidth() + " : " + getHeight() );
DrawingPanel dp = new DrawingPanel();
dp.setPreferredSize( new Dimension( getWidth() , getHeight() - 100 ) );
CommandPanel cp = new CommandPanel( dp );
dp.setPreferredSize( new Dimension( getWidth() , 100 ) );
//------------------------------------------------------------------------------------
// カウンターラベルの参照先をセット --> スレッドにより値をインクリメントさせていく
//------------------------------------------------------------------------------------
dp.setReference( cp.getCounterLabel() );
// 各パネルを配置
contentPane.add( dp, BorderLayout.CENTER );
contentPane.add( cp, BorderLayout.SOUTH );
}
}
戻る