\n
[ トップページ ]
[ ___ _CommandPrompt ]
[ ___ _JScript ]
[ ___ _MySQL ]
[ ___ _Cygwin ]
[ ___ _Java ]
[ ___ _Emacs ]
[ ___ _Make ]
[ ___ _Perl ]
[ ___ _Python ]
[ ___ _OpenGL ]
[ ___ _C# ]
[ ___ _StyleSheet ]
[ ___ _C++ ]
[ ___ _Winsock ]
[ ___ _Thread ]
[ ___ _VisualStudio ]
[ ___ _C ]
[ ___ _Win32API ]
[ ___ _Lua ]
[ ___ _PhotoShop ]
ヘッダ検索
■ チュートリアル(Tutorial)
■ クラス作成
ファイル名と同じ名前のクラスを用意する。
エントリのメソッドは static void main() になる。
// Test.java
public class Test {
public static void main (String[] args) {
System.out.println("Hello World !!" );
}
}
■ Compile
javac.exe をつかってコンパイルする。
バイトコード Test.class が生成される。
■ 実行
実行する class は main() Method をもっていなくてはならない。
バイトコードは仮想マシン ( Java VM )が解釈して実行される。
Test.class を実行するには .class を除いた名前を指定する。
■ 標準入力(stdin)
import java.io.*;
class test {
public static void main(String args[]) {
int i = 0;
System.out.print("何か入力してください>" );
try {
InputStreamReader fp = new InputStreamReader(System.in);
while(true) {
i = fp.read();
if (i == '\n') break;
System.out.print((char)i);
}
fp.close();
}
catch (IOException err) {
System.out.println(err);
}
}
}
■ プロセス(Process)
■ ProcessBuilder
import java.io.*;
ProcessBuilder pb = new ProcessBuilder("notepad" );
Process p = pb.start();
Runtime を使う
Runtime runtime = Runtime.getRuntime();
Process p = runtime.exec("ping localhost" );
// プロセスの標準出力から取得する
InputStream stdIn = p.getInputStream();
int c;
while ( (c = stdIn.read()) != -1 ) {
System.out.print((char)c);
}
stdIn.close();
// プロセスの終了をまつ
int ret = p.waitFor();
System.out.println("retcode = " + ret);
■ リファレンス(REFERENCE)
■ Integer
static Integer getInteger(String nm, Integer val)
static int parseInt(String s)
■ io.OutputStreamWriter
http://www.javaroad.jp/java_io1.htm
OutputStreamWriter は、文字ストリーム -> バイトストリームへの橋渡しの役目
* Stream とは?
[ 読み込み Source ] [ Program ]
// 流れができている状態 を Stream というのか ?
// Buffering しないですむ のが 特徴
[ 読み込み Source ] ------------> [ Program ]
// JSP からも利用可能
{
// Write Sample
File outFile = new File("c:/test.txt" );
// File Class の Instance を使って new する
FileWriter out = new FileWriter( outFile );
// 文字列データ ( \n は別途必要 )
out.write( "test" + "\n" );
out.write( 10 );
// 書き込みストリームをとじる
out.close();
}
■ io.File
* http://www.javaroad.jp/java_io8.htm
* FS 関連の Service を提供する
Fileクラスには
ファイル・ディレクトリの作成、PATH名の調査
read権・write権の調査などファイル・ディレクトリに対して動作する様々なメソッドが用意
Fileクラスのオブジェクトは
FileReaderクラス, FileWriterクラスなどの
ファイル入出力関連のオブジェクトを生成する際の引数としても使用される
■ sql.ResultSet
// ResultSet オブジェクトの現在行にある指定された列の値を
// Java プログラミング言語の int としてとる
int getInt(String columnName)
// 2 OKU をこえる値は long でないと ERROR
int getLong(String columnName)
■ URLEncode
java.net.URLEncoder クラスを使用するために java.net.*パッケージのインポートを宣言
// urlencode の check にも利用できる
// Default が SJIS
String enc = URLEncoder.encode( "あああ" );
// encode() メソッドはスタティックなのでインスタンスを生成せずに使える
String value = URLEncoder.encode( now.toString() );
■ sql.ResultSetMetaData
REF
http://www008.upp.so-net.ne.jp/kikuta/jdbcnote/jdbc5_7.html
DESC
DB の MetaData をとれる
このときは getInt() とか といったメンドイことはしなくても OK
ResultSetMetaData rsmeta = rs.getMetaData();
// column 数
int nrCol = rsmeta.getColumnCount();
// column 型名
String rsmeta.getColumnName( i );
// column 型 ( Enum )
int rsmeta.getColumnType( i );
// column 型名
String rsmeta.getColumnTypeName( i );
out.println( "< table border=1>" );
// Header
out.println( "< tr>" );
for( int i=1; i< =nrCol; i++ ){
String label = rsmeta.getColumnName(i);
out.println( "< th>" + label + "< /th>" );
}
out.println( "< /tr>" );
while(rs.next()){
out.println( "< tr>" );
for( int i=1; i< =nrCol; i++ ){
int type = rsmeta.getColumnType(i);
if ( type == Types.CHAR ) {
out.println( "< td>" + rs.getString( i ) + "< /td>" );
}
else if ( type == Types.INTEGER ) {
out.println( "< td>" + rs.getInt( i ) + "< /td>" );
}
// MySQL で指定した 型と同じ
else if ( type == Types.BIGINT ) {
out.println( "< td>" + rs.getInt( i ) + "< /td>" );
}
}
out.println( "< /tr>" );
}
out.println( "< /table>" );
■ tmp
// 接続元の Client をえる
String host = request.getRemoteHost();
■ System.out
// RET "null" という文字列が表記される
// ( DB のデータをはくときに注意 )
String s = null;
System.out.println( s );
■ util.Date
REF
Date
http://www.javaroad.jp/java_date1.htm
■ util.Calendar
DESC
現在の日付をえる
class Foo
{
public static void main(String[] args) {
Calendar cal1 = Calendar.getInstance(); //オブジェクトの生成
int year = cal1.get(Calendar.YEAR); // 年
int month = cal1.get(Calendar.MONTH) + 1; // 月
int day = cal1.get(Calendar.DATE); // 日
int hour = cal1.get(Calendar.HOUR_OF_DAY); // 時
int minute = cal1.get(Calendar.MINUTE); // 分
int second = cal1.get(Calendar.SECOND); // 秒
StringBuffer dow = new StringBuffer();
switch (cal1.get(Calendar.DAY_OF_WEEK)) { // 曜日
case Calendar.SUNDAY: dow.append("日曜日" ); break;
case Calendar.MONDAY: dow.append("月曜日" ); break;
case Calendar.TUESDAY: dow.append("火曜日" ); break;
case Calendar.WEDNESDAY: dow.append("水曜日" ); break;
case Calendar.THURSDAY: dow.append("木曜日" ); break;
case Calendar.FRIDAY: dow.append("金曜日" ); break;
case Calendar.SATURDAY: dow.append("土曜日" ); break;
}
// 年、月、日、曜日、時、分、秒を表示
System.out.println(year + "/" + month + "/" + day + " " + dow
+ " " + hour + ":" + minute + ":" + second);
}
}
■ sql.Statement
REF
http://www.fireproject.jp/feature/postgresql/programing_jdbc/execute.html#2
// 指定された SQL 文を実行する
int executeUpdate(String sql)
// SELECT 文のときに使う
ResultSet executeQuery(String sql)
■ 文字列
■ lang.String
// 比較
// == はだめらしい strcmp と同じ
int compareTo(String anotherString)
// 文字列の長さ ( 文字数 )
//
int length()
// int -> String へ ( FactoryMethod )
String s = String.valueOf( p );
// i 番目 をとりだす
char c = s.charAt(i);
// Split
// 指定した regexp で分割する
String[] split(String regex)
// 置換
// 2 つめは String
String replaceAll( String regexp, String dst )
{
String path = "c:\\foo\\bar\\foo.txt" ;
// BAD
//path.replaceAll( "\\" , "/" );
//OK
// \\\\ で \\ という文字列が RegExp Engine にわたる
// [\\] は [\] を意味する
//
path.replaceAll( "\\\\" , "/" );
}
// 検索
// みつからなければ -1
int i = s.indexOf( "abc" );
// 部分文字列
// index 1 から 最後まで
s.subString( 1 );
s.subString( 1, 10 );
// Ctor はない
{
int i = 10;
// BAD
//String path = i;
//OK
String path = "" ;
path = i;
}
// 指定した Encode で String をバイトシーケンスに符号化して配列にセット
byte[] getBytes( String code )
{
String s = "ABC" ;
byte[] a = null;
try {
// SJIS Code でバイト列をかえす
a = s.getBytes("SJIS" );
}
catch ( Throwable e ) {
System.out.println( "error" );
}
// RET : 65 66 67
for( int i=0; i< a.length; i++ ){
System.out.println( a[i] );
}
}
BAD
String[] list = ( ret[0][6] ).split("." );
OK
String[] list = ( ret[0][6] ).split("\\." );
■ StringBuffer
POINT
文字列バッファは String と似ているが、変更できる点が異なる。
WARNING
String 型とは互換性はないため、変換が必要
String str = s.toString();
// 長さ
s.length()
// 先頭の文字を消す
s.deleteCharAt( 0 );
// 参照
s.charAt( 0 );
// 追加
s.append( "test" );
// 文字以外でも文字列表現で追加できる
s.append( 0 );
s.append( obj );
// 部分文字列
s.subString( 0, 3 );
// すべて削除
s.delete( 0, s.length() );
WARNING
代入できない
s = "" ;
■ SYNTAX
■ 制御構文
■ for
for( int i=0; i< a.length; i++ ){
s += a[i] + "_" ;
}
System.out.print( s + "," );
■ 型
大きくわけて 2 種類
基本型: boolean、 char、byte、short、int、long、float、double
参照型: クラス型、インタフェース型、配列型
基本型の型変換
データ格納領域がより広い型への変換を要求した時に、暗黙的な型変換をする
だから int -> boolean は当然ない
boolean なし
char int, long, float, double
byte short, int, long, float, double
short int, long, float, double
int long, float, double
long float, double
float double
double なし
基本型のキャスト( C 同様 )
キャストとはプログラマが[ 意識的 ]に行う変換処理
型変換では変数の変換処理をできない時にキャストを使用する
キャストは変換したい型を( )で囲み、変換元の変数の前に指定することでする
■ Cast(型変換)
キャストのルール
boolean 型以外の基本型の変数を、他のbooleanが対外の基本型の変数にキャストできる
キャストはデータ格納領域が広くなるキャストでも、データ格納領域が狭くなるキャストでも OK
データ格納領域が広くなるキャストの場合は、キャストを指定しなくても、
必要な場合には、暗黙的な型変換がされる.
boolean 型はどの型へもキャストできない
■ import
REF
importの機能
DESC
import 宣言をすることで class の指定を 省略できる
// sql 以下を[*] 全指定( wildcard )
import java.sql.*;
// single-type-import
//
import java.util.Date;
// type-import-on-demand
//
import java.util.*
// java.util だけでなく
import java.util.*;
// java.util.jar パッケージのクラスも利用する
import java.util.jar.*;;
WARNING
直下 のみ を検索する
■ Scope
// Block Scope
{
int i = 128;
}
// ERROR : シンボルを見つけられません。
System.out.println( i );
int i = 10;
System.out.println( i );
// block Scope があるくせに, 同一の Symbol ってだめらしい
{
// ここで怒られる
// ERROR : i は main() で定義されています
int i = 10;
System.out.println( "inner = " + i );
}
System.out.println( i );
■ Array(配列)
SYNTAX
型[ ] 配列名;
// int 型の配列 intArray を宣言
int[] intArray;
//
char[] charArray = new char[10];
// 要素数
int nr = a.length;
// 初期化子は配列生成時に直接データを代入して配列を生成する方法です
初期化子を指定した場合の配列サイズは代入するデータの数で決まる
String[] stringArray = {"Sunday" , "Monday" , "Tuesday" };
//String型の配列stringArrayを宣言・生成
■ 予約語(Reserve)
null // NULL でないよ
■ コンテナ(Collection)
■ ArrayList
POINT
ArrayList は sort の機能がない
add() は overload があり 任意の位置にも追加できる
ArrayList() は逐次探索をする
import java.util.*;
ArrayList< String > a = new ArrayList< String >();
a.add( "aaa" );
// 初期バッファサイズを指定する。
// 要素数ではないので注意。
ArrayList( 10 )
// 指定した位置の要素を削除する。
a.remove( 0 );
// 要素数
a.size()
WARNING
[] は利用できない。get(), set() で参照をとる。
a.get( 0 );
a.set( i, 10 );
■ Map
http://www.javaroad.jp/java_collection4.htm
import java.util.*;
public class ExCollection7 {
public static void main(String[] args) {
ExCollection7 exClass = new ExCollection7();
exClass.showFeature(new HashMap(), "HashMap" );
exClass.showFeature(new TreeMap(), "TreeMap" );
exClass.showFeature(new LinkedHashMap(), "LinkedHashMap" );
}
void showFeature(Map exMap, String s) {
String[] tel = {"092" , "06" , "052" , "03" , "011" };
String[] area = {"Fukuoka" , "Osaka" , "Nagoya" , "Tokyo" , "Hokkaido" };
for (int i = 0; i < 5; i++) {
// Mapに 要素 をいれる
exMap.put(tel[i], area[i]);
}
// Map の 要素をみる
System.out.println(s + " = " + exMap);
}
}
■ 例外(Exception)
POINT
RuntimeException 以外は 処理するコードがいる。
コードがない場合はコンパイルエラーになる。
RuntimeException は いつでも発生するため
コンパイラーがチェックする意味がない。
■ try.catch.finally
try {
// 例外をスローする可能性のある処理
}
catch (例外クラス型 引数名) {
// 例外処理(例外ハンドラ)
}
finally { // 任意
// 最後に必ず実行される( したい )処理
// EX file close
}
catch は複数指定できる。
この場合は、例外の派生先の順にすることで具体的なエラー内容を知ることができる。
try {
}
catch {
}
// なんでも うけとると どの例外処理をしたらいいかわからない
catch ( Exception e ) {
}
■ package
目的は
同じ機能をもつものを Group 化して整理する
名前の衝突をふせぐ
Security ( 同一 package 内からのアクセス )
// package 内にあるクラスを利用するには package名をつける
sample.Test
■ packageにクラスをいれる
Package の適用範囲は
File 全体.
Package を指定しないと
DefaultPackage に含まれる
DefaultPackage とは
名前をもたない Package
POINT
Java API の class は どれかの Package にはいる
// パッケージPackageAの作成
package PackageA;
public class Test { //
public void func() {
System.out.println("PackageAに属します" );
}
}
■ packageのクラスを使う
ArrayList は java.util にある
ArrayList の FullName は
POINT
Java の import は FullName の Type を省くため
include とは異なる
import 宣言がなくても class は利用できる
// Class を使うには import する
import java.util.ArrayList;
// または FullName で指定する
java.util.ArrayList< Dog > a = new java.util.ArrayList< Dog >();
// java.lang は例外で FullName で指定する必要がない
// PackageA.ExPackage インポート
import PackageA.ExPackage;
public class ExPackage1 {
public static void main(String[] args) {
ExPackage ex = new ExPackage(); //
ex.showName(); //
}
}
// Compile の指定
javac PackageB/ExPackage2B.java
// dir( package )つきで call しないとだめらしい
java PackageB/ExPackage2B
WARNING
どうやら Directory と Mapping する必要がある
POINT
java. ではじまるのは Sun 公認の package
javax. は 標準拡張 package という
はじめは 拡張 package だが, 標準ライブラリと同じくらい 一般的になった
■ スレッド(Thread)
スレッドとは制御の流れのこと。
マルチスレッドでは複数の制御の流れを作成できる。
POINT
スレッドは "ながら仕事" をする時に使う。
POINT
スレッドは次のケースで使う。
■ スレッドをつくる
スレッドをつくる方法は2つある。
// 仕事をつくる
Runnable job = new MyJob();
// Thread には Job が必要
Thread t = new Thread( job );
// 実行可能 状態になる
t.start();
POINT
Thread には名前をつけることができる。
デバッグをする時に便利。
Thread t = new Thread();
// 名前をつけなくてもデフォルトの名前がつく
t.setName("xxx" );
// 実行中のスレッドの名前をとる
Thread.currentThread().getName();
Runnable を実装したクラスをスレッドで実行する。
// スレッドで実行可能なクラス
class Job implements Runnable
{
public void run() {
while(true) {
System.out.println("thread working" );
}
}
};
public class TestRunable {
public static void main (String[] args) {
Job job = new Job();
Thread t1 = new Thread( job, "test" );
t1.start();
System.out.println("main thread run" );
}
}
WARNING
スレッドの run() は一度しか実行できない。
スレッドへの仕事を繰り返す場合は 無限ループさせる。
t = new Thread();
t.start();
// ERROR
// 一度したスレッドは再度実行できない。
t.start();
public void run() {
while ( true ) {
System.out.println("thread working" );
}
}
■ スレッドクラスを継承する
public class Test extends Thread {
public main() {
}
}
■ スレッドを止める
POINT
スレッドの動作をとめるには次の方法がある。
スレッドの終了をまつ。
WARNING
一度終了したスレッドの再利用( start() )はできない。
明示的に破棄する場合は null を設定して参照を消すこと。
class Test extends Thread {
public static void main ( String args[] ) {
Test t = new Test();
t.start();
// スレッドが生きているか質問する。
while ( t.isAlive() ) {
}
}
public void run() {
System.out.println( "thread working ..." );
}
}
■ スレッドの終了をまつ
main スレッドで isAlive() で質問をしながら待つと CPU 時間を無駄に消費することになる。
そのため join() メソッドで指定したスレッドが停止するまでまつ
// スレッドを実行して
t.start();
// スレッドの終了をまつ
t.join();
// 2 秒まつ
t.join( 2000 );
■ 別のスレッドからとめる
スレッドは run() メソッドが完了すれば, 終了するので
run() メソッドが完了するようにすればいい。
つまり終了条件となる変数の値を変更してしまえばいい。
class TestStop extends Thread {
// 終了条件
static volatile boolean flag = false;
public static void main ( String args[] ) {
TestStop t = new TestStop();
int i = 0;
t.start();
System.out.println("スレッドを止めるには s と入力してください" );
try {
InputStreamReader fp = new InputStreamReader(System.in);
while(true) {
i = fp.read();
if (i == '\n') break;
System.out.print((char)i);
}
fp.close();
}
catch (IOException err) {
System.out.println(err);
}
flag = true;
}
public void run() {
while ( !flag ) {
try {
Thread.sleep( 1000 );
}
catch ( Exception e ) {}
System.out.println( "thread working ..." );
}
}
}
■ プログラムの終了とスレッドの終了
POINT
プログラムが終了するのは, main() スレッドが終了する時ではなく
すべてのユーザースレッドが終了した時に終わる。
スレッドには2種類あり
ユーザースレッドは通常のスレッドの作成でつくられるスレッド。
デーモンスレッドはプログラムが終了するときにスレッドの終了をまつ必要がない。
デーモンスレッドの例として Java の GC がある。
デーモンスレッドにするには, start() の前に setDaemon( true )で設定をする。
public class TestDaemon extends Thread {
public void run() {
while ( true ) {
System.out.println( "daemon thread working" );
}
}
public static void main (String[] args) {
Thread t = new TestDaemon();
t.setDaemon( true );
t.start();
try {
Thread.sleep(1000 * 1);
}
catch ( Exception e ) {}
}
}
■ スレッドの同期(排他)
スレッドは非同期で実行されるが、共有のデータを操作、参照する場合は
矛盾が起きないように処理を同期する必要がある。
つまり相手の動作と合わせる必要があるタイミングがある。
スレッドの同期化とは
1つのリソースに対して2つが同時に操作をしないようにすること。
複数のスレッドで同期をするには モニタを取得する。
スレッド同士を同期する方法は次の2つがある。
synchronized メソッドはメソッドの対象である( this )オブジェクトをロックする。
ロックされた場合、他のスレッドが this に相当するオブジェクトのメソッドを実行しようとすると
処理が待機する。
ロックをしてメソッドの処理が終わったスレッドはロックを解除してメソッドを抜ける。
待機していた別のスレッドはロックをかけて、そのメソッドを開始できる。
オブジェクトが自分のスレッドでロックしているかどうかを調べることもできる
ただし別のスレッドがロックしているかどうかは判断できない。
b = Thread.holdsLock( o );
System.out.println("ロック状態 " + b );
ロックは変数ではなく、その参照先のオブジェクトに対してされる。
synchronized ( o ) {
}
// これも同じ。 holdsLock() でチェックできる。
Object a = o;
synchronized ( o ) {
system.out.println( Thread.holdsLock( a ) );
}
class Toilet
{
synchronized public void enter() {
String s = Thread.currentThread().getName();
System.out.print( s );
for( int j=0; j< 50; j++ ){
System.out.print( "=" );
}
System.out.print( ">\n" );
}
}
class Human extends Thread
{
Toilet t;
Human( Toilet t ) {
this.t = t;
}
public void run() {
while (true) {
t.enter();
}
}
}
public class TestSync extends Thread
{
public static void main (String[] args) {
Toilet t = new Toilet();
Human h = new Human(t);
h.setName( "foo" );
h.start();
Human h1 = new Human(t);
h1.setName( "bar" );
h1.start();
}
}
■ ロックをすることは書き込み禁止とは異なる
POINT
ロック/アンロックはモニタの取得、解放を意味するだけ。
オブジェクトの変数の設定はできてしまう。
■ タイマーを使って画像を定期的にきりかえる
■ デッドロック
POINT
複数のスレッドがお互いがロックしている
オブジェクトをロックしようとするとデッドロックが発生する。
デッドロックを回避するには、ロックする順番を決めておくとよい。
デッドロックを起こす要因として, suspend() がある。
オブジェクトをロックした状態で suspend() をするとデッドロックの可能性があるため
利用しないほうがよい。
stop() はロック中のオブジェクトを解放するが、
処理が任意のタイミングで中断されるため、作成途中のオブジェクトができるため
利用しない方がいい。
■ スレッドを連携させる
スレッド間で連携した処理をするには 待機 と 通知 を使う。
あるスレッドで変更があった場合に、別のスレッド側へ通知をしてもらう。
その間は待機することで、無駄な時間( CPU 割あて )をなくすことができる。
オブジェクトの変更があるまで, 待機して変更があったら通知してもらうことで
無駄な待ち時間や処理が不要になる。
notify()/notifyAll() を利用する。
wait() メソッドでオブジェクトの状態が変更されるまで一時停止して待ち
POINT
wait() する側は状態の変更を待つ側
オブジェクトの状態が変わるまで待ちたい場合は, wait() を使う。
notifyAll() を使うと、 obj に対して待機しているすべてのスレッドに通知される。
public class TestWait extends Thread
{
boolean flag = false;
static Object o = new Object();
public static void main (String[] args) {
TestWait t = new TestWait();
t.start();
try {
Thread.sleep( 5000 );
}
catch ( Exception e ) {}
System.out.println("変更があったので、通知します。" );
try {
Thread.sleep( 1000 );
}
catch ( Exception e ) {}
// notify() するスレッドは、wait() と同じく obj をロックする必要がある。
synchronized( o ) {
o.notify();
}
}
public void run() {
try {
Thread.sleep( 3000 );
}
catch ( Exception e ) {}
// wait() を実行するスレッドは obj をロックする必要がある。
// ロックをしないと、 java.lang.IllegalMonitorStateException が発生して wait() に失敗する。
synchronized( o ) {
try {
System.out.println("待機しています。" );
o.wait();
}
catch ( Exception e ) {
System.out.println("throw" );
}
}
System.out.println( "thread working ..." );
}
}
wait() はタイムアウトの指定もできる。
notify() がなくても指定時間が過ぎたらスレッドを再開する。
■ キーボード入力したコマンドラインをスレッド側で実行する
public class TestWait2 extends Thread
{
static StringBuffer o = new StringBuffer();
public static void main (String[] args) {
TestWait2 t = new TestWait2();
t.start();
int i = 0;
InputStreamReader fp = new InputStreamReader(System.in);
try {
Thread.sleep( 500 );
}
catch ( Exception e ) {}
while (true) {
try {
Thread.sleep( 1000 );
}
catch ( Exception e ) {}
System.out.println("文字を入力してください。" );
StringBuffer st = new StringBuffer();
try {
while(true) {
i = fp.read();
if (i == '\n') break;
System.out.print((char)i);
st.append( (char)i );
}
//fp.close();
}
catch (IOException err) {
System.out.println(err);
}
o.delete( 0, o.length() );
o.append( st );
// notify() するスレッドは、wait() と同じく obj をロックする必要がある。
System.out.println("変更があったので通知します。" );
synchronized( o ) {
o.notify();
}
}
}
// うけとった文字列を cmdline として実行する
void cmdlineJob( String s ) {
try {
String t = Thread.currentThread().getName();
System.out.println( t + "cmdlineJob = " + s );
Runtime runtime = Runtime.getRuntime();
Process p = runtime.exec( s );
InputStream stdIn = p.getInputStream();
int c;
while ( (c = stdIn.read()) != -1 ) {
System.out.print((char)c);
}
stdIn.close();
int ret = p.waitFor();
System.out.println("retcode = " + ret);
}
catch ( Exception e ) {
System.out.println("fail" );
}
}
// スレッド側では キーボード文字の入力があった場合に処理を実行をする。
public void run() {
while ( true ) {
String s = Thread.currentThread().getName();
// wait() を実行するスレッドは obj をロックする必要がある。
// ロックをしないと、 java.lang.IllegalMonitorStateException が発生して wait() に失敗する。
synchronized( o ) {
try {
System.out.println( s + "待機しています。" );
o.wait();
}
catch ( Exception e ) {
System.out.println("throw" );
}
cmdlineJob( o.toString() );
}
}
}
}
■ スレッドの優先度をつける
スレッドの優先度をつけるには Thread.setPriority() を使う。
スケジューラは実行可能状態のスレッドのうち、優先度の高いものを実行する。
優先度は 1 - 10 で指定して、値が大きいほど優先度は高い。
POINT
マルチコアの環境では、実際に複数同時に実行できるため
コア数より少ないスレッドの場合は数が同じくらいになる可能性がある。
カウントを表示して優先度の効果を確かめてみる。
// スレッドへのお仕事
class Job implements Runnable
{
volatile public int cnt = 0;
// スレッドに実行させるメソッド
public void run() {
System.out.println("do job" );
while ( true ) {
cnt ++;
}
}
}
public class TestPriority {
public static void main (String[] args) {
ArrayList< Job > a = new ArrayList< Job >();
int nr = 10;
int i = 0;
for( i=0; i< nr; i++ ){
Job job = new Job();
Thread t = new Thread( job, "t1" );
t.setPriority( (i%10) + 1 );
t.start();
a.add( job );
}
while ( true ) {
try {
Thread.sleep(3000 * 1);
}
catch ( Exception e ) {}
for( i=0; i< nr; i++ ){
System.out.println( " job " + (i+1)%10 + " " + a.get(i).cnt );
}
}
}
}
■ スレッドの処理を割り込む
待機中( wait(), sleep(), join() )のスレッドの処理に強制的に再開するには interrupt() を使う。
これによって メインスレッドが終了する時点で,
待機中のスレッドを停止させることができる。
■ GUI
POINT
Java では GUI の構成要素を Component という
javax.swing.JComponent を継承する
■ Window
ウィンドウをつくるには JFrame を作成して表示する。
JFrame も GUI コンポーネントのひとつ。
import javax.swing.*;
import java.awt.*;
public static void main() {
// フレーム( ウィンドウ )を作成。
JFrame f = new JFrame();
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
// 大きさの設定
f.setSize( 300, 300 );
// 位置の設定
f.setLocation( 100, 100 );
// 表示する。
f.setVisible( true );
}
メインスレッドを止めても, GUI の操作は受け付けるらしい。
// 表示する。
f.setVisible( true );
// 無限ループ
while ( true ) {
System.out.print("." );
}
■ ボタン(Button)
すべての GUI コンポーネントはフレームに追加することで、配置される。
JFrame f = new JFrame();
JButton b = new JButton( "click me" );
f.getContentPane().add( BorderLayout.EAST, b );
ボタンのコールバックを受け取るにはリスナーを追加する。
リスナーに登録するには ActionListener を実装する。
class MyListener implements ActionListener {
public void actionPerformed( ActionEvent e ) {
System.out.println( "button clicked" );
}
}
ボタンオブジェクトに対してリスナー( コールバック )を登録する。
b.addActionListener( new MyListener() );
■ グラフィック(Graphic.Swing)
グラフィックを描画するには JFrame.paint(Graphics g) メソッドをオーバーライドする。
Graphics は描画のためのメソッドと共にグラフィックスのステートをもつ。
class MyFrame extends JFrame {
public void paint(Graphics g){
super.paint( g );
// カラーステートを青に変更
g.setColor(Color.BLUE);
g.drawRect(10,60,280,180);
// 位置 と 大きさ を指定
fillRect( int x, int y, int width, int height );
g.fillOval(100,100,100,100);
// テキストを描く
g.drawString("Swing Test" , 10, 50);
}
MyFrame() {
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
setSize( 300, 300 );
setVisible( true );
}
public static void main() {
JFrame f = new MyFrame();
}
}
ボタンを押したら色を変更するためにボタンのリスナーになる。
class MyFrame extends JFrame implements ActionListener {
int flag = 0;
public void actionPerformed( ActionEvent e ) {
flag ++;
// 画面を更新するには再描画を要求する。
repaint();
}
}
ボタンの種類を判別するには, ActionEvent.getActionCommand() を利用する。
ラベルの文字列が返ってくるので判別できる。
if ( e.getActionCommand() == "click me" ) {
System.out.println( "button clicked go" );
}
else {
System.out.println( "NOT button clicked stop" );
}
■ 画像を表示する
public void paint(Graphics g){
super.paint( g );
Image i = new ImageIcon( "d:/test.jpg" ).getImage();
g.drawImage( i, 0, 0, this );
}
■ ネットワーク(Network)
■ Socket
シンプル HTTP クライアント
import java.io.*;
import java.net.*;
public class HttpClient {
PrintWriter writer;
Socket soc;
public void doIt() {
try {
soc = new Socket( "127.0.0.1" , 8080 );
writer = new PrintWriter( soc.getOutputStream() );
//InputStreamReader s = new InputStreamReader( soc.getInputStream() );
System.out.println( "Network につながりました " );
}
catch ( IOException e ) {
e.printStackTrace();
}
// HTTP メッセージを投げる
writer.println( "GET / HTTP/1.0\r\n\r\n" );
try {
InputStreamReader s = new InputStreamReader( soc.getInputStream() );
int i = 0;
while(true) {
i = s.read();
if (i == -1) break;
System.out.print((char)i);
}
}
catch ( Exception ex ){}
}
static void main() {
new HttpClient.doIt();
}