複数スレッドで素数を計算するタスクを分業させる

戻る



import java.util.*;

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

/**
<pre>
$Id: pns.html,v 1.1 2009/06/22 16:12:19 kishi Exp kishi $
</pre>
@author KISHI Yasuhiro 
*/

public class GlobalControllerPanel extends JPanel {

    private JButton allStartButton;
    private JButton allStopButton;

    public GlobalControllerPanel() {

        setLayout( new GridLayout( 1, 2 ) );

        allStartButton = new JButton( "START ALL" );
        allStartButton.setBackground( Color.green );

        allStopButton = new JButton( "STOP ALL" );
        allStopButton.setBackground( Color.red );

        this.add( allStartButton );
        this.add( allStopButton );

    }

    public JButton getAllStartButton() {
        return this.allStartButton;
    }
    public JButton getAllStopButton() {
        return this.allStopButton;
    }
}
import java.util.*;

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

/**
<pre>
$Id: pns.html,v 1.1 2009/06/22 16:12:19 kishi Exp kishi $
</pre>
@author KISHI Yasuhiro 
*/

public class LeftPanel extends JPanel implements ActionListener {

    private OperationPanel[] oPanels;
    private GlobalControllerPanel gcp;
    private final String START_ALL = "START_ALL";
    private final String STOP_ALL = "STOP_ALL";

    public LeftPanel( int oPanelCount ) {
        setLayout( new GridLayout( 1 + oPanelCount, 1 ) );

        // 全体を制御するボタンを格納したパネルを配置
        gcp = new GlobalControllerPanel();
        this.add( gcp );

        JButton allStartButton = gcp.getAllStartButton();
        allStartButton.addActionListener( this );
        allStartButton.setActionCommand( START_ALL );

        JButton allStopButton = gcp.getAllStopButton();
        allStopButton.addActionListener( this );
        allStopButton.setActionCommand( STOP_ALL );

        //---------------------------------------------
        // 指定された数だけパネルを追加する
        //---------------------------------------------
        oPanels = new OperationPanel[ oPanelCount ];

        // 計算する範囲を指定された数だけ分割した場合の範囲を求める
        // long[][] ranges = PrimeFactors.getDividedRanges( oPanelCount );
        // for ( int i = 0; i < ranges.length; i++ ) {
        //     System.out.println( i );
        //     System.out.println( "from: " + ranges[ i ][ 0 ] + "\t" + "to: " + ranges[ i ][ 1 ] );
        // }

        for ( int i = 0;i < oPanelCount;i++ ) {
            oPanels[ i ] = new OperationPanel();
            this.add( oPanels[ i ] ); // パネルを配置

            allStartButton.addActionListener( oPanels[ i ] );
            allStopButton.addActionListener( oPanels[ i ] );

            //-----------------------------------
            // 計算開始ポイントを引き渡す
            //-----------------------------------
            oPanels[ i ].setInitialParameters( i, Long.MAX_VALUE, oPanelCount );
        }
    }

    /** ここでアクションを拾う必要はないかもしれない */
    public void actionPerformed( ActionEvent e ) {
        String action = e.getActionCommand();
        if ( START_ALL.equals( action ) ) {
            System.out.println( "in LeftPanel: [" + action + "] が選択されました!" );
        }
        if ( STOP_ALL.equals( action ) ) {
            System.out.println( "in LeftPanel: [" + action + "] が選択されました!" );
        }

    }

}
import java.util.*;

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

/**
<pre>
$Id: pns.html,v 1.1 2009/06/22 16:12:19 kishi Exp kishi $
</pre>
@author KISHI Yasuhiro 
*/

public class OperationPanel extends JPanel implements ActionListener {

    // private SimpleCounter sc;

    // 素数を求めるオブジェクト
    private PrimeNumberCalculator pnc;

    private long fromNumber;
    private long toNumber;
    private int pitch;

    private JButton button;
    private JLabel label;
    /** 処理中かどうかのフラグ */
    private boolean runningStatus = false;

    public OperationPanel() {
        setLayout( new GridLayout( 1, 2 ) );

        button = new JButton( "開始" );
        label = new JLabel( "sleeping..." );

        this.add( button );
        this.add( label );

        button.addActionListener( this );
        button.setActionCommand( "CHANGE_STATUS" );
    }

    public void setInitialParameters( long fromNumber, long toNumber, int pitch ) {
        this.fromNumber = fromNumber;
        this.toNumber = toNumber;
        this.pitch = pitch;

        System.out.println( "in OperationPanel: pitch = " + pitch );
    }

    public JButton getButton() {
        return this.button;
    }

    public void actionPerformed( ActionEvent e ) {
        String action = e.getActionCommand();

        if ( "CHANGE_STATUS".equals( action ) ) {
            System.out.println( "in OperationPanel: ボタンがクリックされました!" );

            /** ON/OFFを指定する */
            reverseRunningStatus();
            manageThread();
        }

        if ( "START_ALL".equals( action ) ) {
            System.out.println( "in OperationPanel: [" + action + "] が選択されました!" );

            startup();
        }
        if ( "STOP_ALL".equals( action ) ) {
            System.out.println( "in OperationPanel: [" + action + "] が選択されました!" );

            shutdown();
        }


        /** テキストを書き換える */
        modifyText();
    }

    private void startup() {
        /* 停止中の場合のみ実行される */
        if ( !runningStatus ) {
            runningStatus = true;
            manageThread();
        }
    }

    private void shutdown() {
        /* 起動中の場合のみ実行される */
        if ( runningStatus ) {
            runningStatus = false;
            manageThread();
        }
    }

    private void reverseRunningStatus() {
        // 反転させる
        runningStatus = !runningStatus;
        System.out.println( "現在のステータスは、" + runningStatus + "です。" );

    }

    /** スレッドの起動停止 */
    private void manageThread() {
        if ( runningStatus ) {
            if ( pnc == null ) {

                System.out.println( "開始されました!" + fromNumber + " - " + toNumber );
                pnc = new PrimeNumberCalculator( fromNumber, toNumber, pitch );

                Thread myThread = new Thread( pnc );
                // スレッド開始
                myThread.start();
            }

        } else {

            if ( pnc != null ) {
                System.out.println( "終了いたしました!" );

                // スレッドを停止させるためにステータスをfalseにする
                // Thread.stop()は推奨されないので使わない!
                pnc.setRunningStatus( false );
                pnc = null; // 明示的な開放

            }

        }
    }

    private void modifyText() {
        if ( runningStatus ) {
            button.setText( "停止" );
            label.setText( "now processing..." );
        } else {
            button.setText( "開始" );
            label.setText( "sleeping..." );
        }

    }
}
import java.io.*;
import java.util.*;

/**
$Id: pns.html,v 1.1 2009/06/22 16:12:19 kishi Exp kishi $
<pre>素因数を計算するクラス</pre>
@author KISHI Yasuhiro
*/

public class PrimeFactors {
    private List factors;
    private long num;

    public PrimeFactors( long num ) {
        this.num = num;

        if ( num == 0 )
            return ;
        calc();
    }

    /** 力ずくのタコロジックで計算する(^^)*/
    private void calc() {

        factors = new LinkedList();

        long targetIntValue = num;
        for ( long i = 2;i < targetIntValue;i++ ) {
            while ( targetIntValue % i == 0 ) {
                factors.add( i );
                targetIntValue /= i;

                try {
                    /** 処理する数字が余りにも巨大だと割り込みできなくってしまうので、少しだけ眠らせる */
                    Thread.sleep( 100 );

                } catch ( Exception e ) {
                    e.printStackTrace();
                }
            }
        }

        /** 1以外は表示しない */
        if ( targetIntValue != 1 ) {
            factors.add( targetIntValue );
        }
    }

    public List getFactors() {
        return factors;
    }

    /** 素数であるか否かを返す */
    public boolean isPrimeNumber() {
        return ( factors != null && factors.size() == 1 );
    }

    public void showList() {
        if ( factors == null )
            return ;

        Iterator iterator = factors.iterator();
        System.out.print( num + "\tは右記の素因数で構成されています。[ " );
        while ( iterator.hasNext() ) {
            System.out.print( iterator.next() + " " );
        }
        System.out.println( "]" );
    }

    static public long[][] getDividedRanges( int divisionCount ) {
        long[][] ranges = new long[ divisionCount ][];

        long pitch = Long.MAX_VALUE / divisionCount;

        int i;
        for ( i = 0; i < divisionCount;i++ ) {
            ranges[ i ] = new long[ 2 ];

            ranges[ i ][ 0 ] = i * pitch;
            ranges[ i ][ 1 ] = ( i + 1 ) * pitch - 1;
        }

        // 最後は割り算の誤差が出るので、強制的にLong.MAX_VALUEをセット
        ranges[ divisionCount - 1 ][ 1 ] = Long.MAX_VALUE;

        return ranges;
    }

    /** 単体試験用のメインメソッド */
    public static void main( String[] args ) {

        if ( args.length != 2 ) {
            System.out.println( "java -cp . PrimeFactors [fromInteger] [toInteger]" );
            System.exit( 1 );
        }
        long from = new Long( args[ 0 ] ).longValue();
        long to = new Long( args[ 1 ] ).longValue();

        for ( long i = from;i <= to;i++ ) {
            PrimeFactors pf = new PrimeFactors( new Long( i ).longValue() );
            pf.showList();
            if ( pf.isPrimeNumber() ) {
                System.out.println( "-- " + i + " は素数です。" );
            }
        }

        System.out.println( "Long型で取り得る整数の最大値は、" + Long.MAX_VALUE + "です。" );

        System.out.println( "計算する範囲を5分割した場合の範囲は以下の通りです。" );
        long[][] ranges = PrimeFactors.getDividedRanges( 5 );
        for ( int i = 0; i < ranges.length; i++ ) {
            System.out.println( i );
            System.out.println( "from: " + ranges[ i ][ 0 ] + "\t" + "to: " + ranges[ i ][ 1 ] );
        }

    }
}

import java.util.*;

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

/**
$Id: pns.html,v 1.1 2009/06/22 16:12:19 kishi Exp kishi $
@author KISHI Yasuhiro
*/
public class PrimeNumberCalculator implements Runnable {

    private long fromNumber;
    private long toNumber;
    private int pitch;
    private long index = 0;
    private boolean runningStatus;

    public PrimeNumberCalculator( long fromNumber, long toNumber, int pitch ) {
        this.fromNumber = fromNumber;
        this.toNumber = toNumber;
        this.pitch = pitch;

        System.out.println( "in PrimeNumberCalculator: pitch=" + pitch );

        runningStatus = true;
    }

    public void run() {

        index = fromNumber;

        while ( runningStatus && index <= toNumber ) {

            System.out.println( "index=" + index );
            PrimeFactors pf = new PrimeFactors( index );
            if ( pf.isPrimeNumber() ) {
                System.out.println( "-- " + index + " は素数です。" );
            }

            index += ( long ) pitch; // 次の計算対象の整数を得る

            try {
                Thread.sleep( 500 );
            } catch ( Exception exception ) {
                exception.printStackTrace();
            }
        }
    }

    public void setRunningStatus( boolean runningStatus ) {
        this.runningStatus = runningStatus;
    }


}
import java.util.*;

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

/**
$Id: pns.html,v 1.1 2009/06/22 16:12:19 kishi Exp kishi $
@author KISHI Yasuhiro
*/

public class PrimeNumberSeeker extends JFrame {

    public static void main( String args[] ) {
        new PrimeNumberSeeker().setVisible( true );
    }

    public PrimeNumberSeeker() {
        setTitle( "素数を複数スレッドで分業して求める" );
        setDefaultCloseOperation( EXIT_ON_CLOSE );

        // BoxLayoutの作成
        BoxLayout layout = new BoxLayout( getContentPane(), BoxLayout.X_AXIS );
        getContentPane().setLayout( layout );

        Dimension size = new Dimension( 400, 600 );

        // 左側のパネル
        LeftPanel leftPanel = new LeftPanel( 20 );
        getContentPane().add( leftPanel );

        // 右側のパネル
        JLabel second = new JLabel( "皆さんこんにちは!", SwingConstants.CENTER );
        second.setForeground( Color.black );
        second.setMaximumSize( size );
        second.setMinimumSize( size );
        second.setPreferredSize( size );

        getContentPane().add( second );

        pack();

    }

}
import java.util.*;

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

/**
$Id: pns.html,v 1.1 2009/06/22 16:12:19 kishi Exp kishi $
@author KISHI Yasuhiro
*/
public class SimpleCounter implements Runnable {

    private int i = 0;
    private boolean runningStatus;

    public SimpleCounter( int start ) {
        i = start;
        runningStatus = true;
    }

    public void run() {

        while ( runningStatus ) {
            i++;

            System.out.println( "i=" + i );

            try {
                Thread.sleep( 500 );
            } catch ( Exception exception ) {
                exception.printStackTrace();
            }
        }
    }

    public void setRunningStatus( boolean runningStatus ) {
        this.runningStatus = runningStatus;
    }


}


戻る inserted by FC2 system