スレッドを使うと次の NewHeat1Dv3.java (実行は http://nalab.mind.meiji.ac.jp/~mk/labo/java/sample/NewHeat1Dv3.html) のようになる。
1 /* 2 * NewHeat1Dv3.java 3 * version 2.0: 計算スレッドを用意した。 4 * version 3.0: ボタン、テキスト・フィールドなどを用意して再計算可能にした。 5 * version 4.0: (予定) 陰解法、境界条件の一般化 6 * version 5.0: (予定) 初期条件の種類を増やす 7 */ 8 9 import java.awt.Button; 10 import java.awt.Color; 11 import java.awt.Frame; 12 import java.awt.Graphics; 13 import java.awt.Image; 14 import java.awt.Label; 15 import java.awt.TextField; 16 import java.awt.event.ActionEvent; 17 import java.awt.event.ActionListener; 18 import java.awt.event.WindowAdapter; 19 import java.awt.event.WindowEvent; 20 21 public class NewHeat1Dv3 extends Frame implements Runnable,ActionListener { 22 /** 23 * 24 */ 25 private static final long serialVersionUID = 1L; 26 /** 27 * 28 */ 29 static final int ImgX = 500, ImgY = 500; 30 static final int WinX = ImgX + 200, WinY = ImgY; 31 Thread th = null; 32 Image im = null; 33 Graphics bg = null; 34 int i, n = -1, nMax; 35 int N; 36 double lambda, Tmax, dt, theta; 37 double h, tau; 38 int skip; 39 double [] x, u, newu; 40 double ratiox, ratioy, X0, Y0; 41 private String[] labelStr={"N", "lamba", "Tmax", "dt", "theta"}; 42 private Label[] label; 43 private String[] txStr={"100", "0.5", "1.0", "0.01", "0.5"}; 44 private TextField[] tf; 45 private String[] btStr = {"Start", "End"}; 46 private Button[] bt; 47 private void readParameters() { 48 N = Integer.parseInt(tf[0].getText()); 49 lambda = Double.valueOf(tf[1].getText()).doubleValue(); 50 Tmax = Double.valueOf(tf[2].getText()).doubleValue(); 51 dt = Double.valueOf(tf[3].getText()).doubleValue(); 52 theta = Double.valueOf(tf[4].getText()).doubleValue(); 53 } 54 public NewHeat1Dv3() { 55 this.setSize(WinX, WinY); 56 this.addWindowListener(new WindowAdapter() { 57 public void windowClosing(WindowEvent ev) { 58 System.exit(0); 59 } 60 }); 61 setLayout(null); 62 bt = new Button[btStr.length]; 63 for (int i = 0; i < bt.length; i++) { 64 bt[i] = new Button(btStr[i]); 65 bt[i].addActionListener(this); 66 bt[i].setBounds(ImgX, (i+2)*20, (WinX - ImgX)/2, 20); 67 add(bt[i]); 68 } 69 label = new Label[labelStr.length]; 70 tf = new TextField[txStr.length]; 71 for (int i = 0; i < labelStr.length; i++) { 72 label[i] = new Label(labelStr[i]); 73 tf[i] = new TextField(txStr[i]); 74 label[i].setBounds(ImgX, (i+bt.length+2)*20, (WinX - ImgX) / 3, 20); 75 tf[i].setBounds(ImgX + (WinX-ImgX)/3, (i+bt.length+2)*20, (WinX-ImgX)/2, 20); 76 add(label[i]); 77 add(tf[i]); 78 } 79 this.setVisible(true); 80 bt[0].setEnabled(false); 81 space(-0.1, -0.1, 1.1, 1.1); 82 // 計算開始の準備 83 initcomputation(); 84 // 計算スレッドを開始する 85 this.start(); 86 } 87 public void start() { 88 if (th == null) { 89 th = new Thread(this); 90 th.start(); 91 } 92 } 93 public void stop() { 94 if (th != null) { 95 th = null; 96 } 97 } 98 public static void main(String[] args) { 99 new NewHeat1Dv3(); 100 } 101 // 座標変換の仕組み 102 private void space(double x0, double y0, double x1, double y1) { 103 X0 = x0; Y0 = y0; 104 ratiox = ImgX / (x1 - x0); 105 ratioy = ImgY / (y1 - y0); 106 } 107 // x座標をユーザー座標からウィンドウ座標に 108 private int wx(double x) { 109 return (int)Math.rint(ratiox * (x - X0)); 110 } 111 // y座標をユーザー座標からウィンドウ座標に 112 private int wy(double y) { 113 return ImgY - (int)Math.rint(ratioy * (y - Y0)); 114 } 115 // 初期データ 116 private double f(double x) { 117 if (x <= 0.5) 118 return x; 119 else 120 return 1.0 - x; 121 } 122 // 現在の u[] をグラフ化する 123 private void drawGraph() { 124 if (bg == null) 125 repaint(); 126 for (int i = 0; i < N; i++) 127 bg.drawLine(wx(x[i]), wy(u[i]), wx(x[i+1]), wy(u[i+1])); 128 } 129 // ダブルバッファリングの定跡 130 public void paint(Graphics g) { 131 if (im == null) { 132 // createImage() はコンストラクターでは使えず、このタイミングでするしかないとか。 133 im = this.createImage(this.getWidth(), this.getHeight()); 134 bg = im.getGraphics(); 135 } 136 g.drawImage(im, 0, 0, this); 137 } 138 private void initcomputation() { 139 // パラメーターを読む 140 readParameters(); 141 // 刻み幅を決める 142 h = 1.0 / N; 143 tau = lambda * h * h; 144 // 145 skip = (int)Math.rint(dt / tau); 146 if (skip <= 0) skip = 1; 147 nMax = (int)Math.ceil(Tmax / tau); 148 // ベクトルを3本用意する 149 x = new double [N+1]; 150 u = new double [N+1]; 151 newu = new double [N+1]; 152 // 153 n = -1; 154 System.out.println("init"); 155 } 156 // 計算スレッド 157 public void run() { 158 while (th != null) { 159 if (n == -1) { 160 // 初期値を計算する 161 for (int i = 0; i <= N; i++) 162 x[i] = i * h; 163 for (i = 0; i <= N; i++) 164 u[i] = f(i * h); 165 n++; 166 repaint(); 167 bg.setColor(Color.white); 168 bg.fillRect(0, 0, ImgX, ImgY); 169 bg.setColor(Color.black); 170 drawGraph(); 171 repaint(); 172 try { 173 Thread.sleep(10); 174 } catch (Exception ex) { 175 ex.printStackTrace(); 176 } 177 } 178 else if (n < nMax) { 179 do { 180 for (i = 1; i < N; i++) 181 newu[i] = (1 - 2 * lambda) * u[i] + lambda * (u[i + 1] + u[i - 1]); 182 for (i = 1; i < N; i++) 183 u[i] = newu[i]; 184 u[0] = 0.0; 185 u[N] = 0.0; 186 n++; 187 } while (n % skip != 0); 188 drawGraph(); 189 repaint(); 190 try { 191 Thread.sleep(10); 192 } catch (Exception ex) { 193 ex.printStackTrace(); 194 } 195 // System.out.println(""+ n * tau); 196 } 197 Thread.yield(); 198 } 199 } 200 public void actionPerformed(ActionEvent e) { 201 // TODO 自動生成されたメソッド・スタブ 202 if (e.getSource() == bt[0]) { 203 bt[0].setEnabled(false); 204 bt[1].requestFocus(); 205 bt[1].setEnabled(true); 206 initcomputation(); 207 start(); 208 } 209 if (e.getSource() == bt[1]) { 210 bt[0].setEnabled(true); 211 bt[0].requestFocus(); 212 bt[1].setEnabled(false); 213 stop(); 214 } 215 } 216 }