isAlive and Join in java

Hôm nay chúng ta sẻ trình bày cách sử dụng 2 đối tượng isAlive method, vs Join method trong thread.

boolean isAlive()

  1. return true : Thread này đang running.
  2. return false : Thread này đang blocked or Die ( Không thể xác định được nó blocked/die 

void join()

  1. Chờ đợi cho đến khi các thread cùng join cùng chết hết rồi mới chết =]] ( Ví dụ chúng ta có 3 thread , chúng ta không xác định được ai chết trước, chết sau …nếu chúng ta join 3 thread này giống như chúng ta kết nghĩa huynh đệ , không xin cùng ngày cùng tháng cùng năm, nhưng nguyện chết cùng ngày cùng tháng cùng năm  =]] . Cả 3 sẻ được chết chung tại 1 thời điểm Cho dù 1 trong 3 xong nhiệm vụ từ rất lâu ).

Sau đây chúng ta có code như sau :

<br />
package com.gcs.demo1;

public class MyThread implements Runnable{
	int seconds; // seconds to sleep
	String name; // name's thread

	public MyThread(int seconds, String name) {		
		this.seconds = seconds;
		this.name = name;
	}

	public void run() {
		System.out.println(name + " is running ... " + seconds/1000 + " seconds");
		pause();
		System.err.println(name + " finished ... !");
	}

	private void pause(){
		try {
			Thread.sleep(seconds);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

MainThread.java của chúng ta

</span></p>
package com.gcs.demo1;

public class MainThread {
	public static void main(String[] args) throws InterruptedException {
		Thread tA = new Thread(new MyThread(10000, "Thread A")); // run in 10 seconds
		Thread tB = new Thread(new MyThread(5000, "Thread B"));  //  run in 5 seconds
		Thread tC = new Thread(new MyThread(2000, "Thread C"));  //  run in 2 seconds

		tA.start();
		tB.start();
		tC.start();

		Thread.sleep(1000);

		// Check is alive
		System.out.println("\tThead A is alive =&gt; " + ((tA.isAlive()) ? "Running" : "Die"));
		System.out.println("\tThead B is alive =&gt; " + ((tB.isAlive()) ? "Running" : "Die"));
		System.out.println("\tThead C is alive =&gt; " + ((tC.isAlive()) ? "Running" : "Die"));

		tB.join();
		tC.join();

		// Check again
		System.out.println("\tThead A is alive =&gt; " + ((tA.isAlive()) ? "Running" : "Die"));
		System.out.println("\tThead B is alive =&gt; " + ((tB.isAlive()) ? "Running" : "Die"));
		System.out.println("\tThead C is alive =&gt; " + ((tC.isAlive()) ? "Running" : "Die"));

	}

}

Kết quả sẻ là : B and C sẻ chết cùng 1 lúc cho dù C run trong 2 seconds, nhưng vì B run trong 5 seconds nên nó củng phải chờ đến 3 seconds nửa mới die. Còn Thread A người dưng nước lả =]] sống sao chết sao thì do nó =]]

d1

Giờ chúng ta cho 3 thằng kết nghĩa luôn

tA.join();
tB.join();
tC.join();

Kết quả chúng ta củng dự đoán được 3 thằng sẻ được chết cùng nhau và sau 10 seconds làm việc vì thằng A có thể sống tới 10 seconds.
d1

Chúc các bạn thành công !!!

Thread Pool – Socket in java

Vấn đề được đặc ra ở đây ứng dụng của chúng ta là Client – Server giao tiếp thông qua Socket.

Chúng ta có thể có rất nhiều client truy cập vào server cùng 1 thời điểm điều này có thể dẫn tới có quá nhiều client truy cập cùng 1 lúc sẻ dẫn tới sập hệ thống ( DDOS ) cách tấn công thường dùng nhứt.

Vậy làm sao để ta giới hạn được việc truy cập của người dùng (Client ).

Có nhiều cách thức để chúng ta làm việc như vậy các bạn có thể tham khảo với các từ khóa như Blocking Queues, Thrad-Safe Collection, Executors.

Bài hôm nay mình hướng dẫn các bạn dùng Executors để thạo ra 1 Thread Pool.

Cực kì đơn giản và cực kí hữu ích

  • Chúng ta tạo ra 1 cái Pool có giới thạn với 4 Thread.
  • ExecutorService tasks = Executors.newFixedThreadPool(4);

Để thực hiện 1 Thread chúng ta sẻ gọi tasks.execute(YOUR_RUNNABLE_OR_CALLABLE)

Bài làm củng chúng ta như sau :

Client của chúng ta : Client.java // chúng ta tạo ra 10 Client truy cập vào Server

package com.gcs.client;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {
	private String name = "";

    public Client(String name) {
		this.name = name;
	}

    public void connectServer(String server, int port){
        try {

            Socket s = new Socket(server, port);
            // send data to server
            PrintWriter writer = new PrintWriter(s.getOutputStream(),true);
            writer.println(name);

            s.close();

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

	public static void main(String[] args) {
        for(int i=1; i<=10; i++){
        	Client client = new Client("Client " +i);
        	client.connectServer("127.0.0.1", 8989);
        }

    }
}

Đây là Server của chúng ta Server.java – Tạo ra thread 4 chỉ cho phép 4 client truy cập tại 1 thời điểm

package com.gcs.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Server {

    public static void main(String[] args) {
        Server myServer = new Server();
        myServer.publicServer();
    }

    public void publicServer(){
        try {
            ServerSocket serverSocket = new ServerSocket(8989);
            System.out.println("Server start connect.....");
            ExecutorService tasks = Executors.newFixedThreadPool(4);

            while(true){
                Socket sock = serverSocket.accept();                
                tasks.execute(new HandlerClient(sock));                                            
            }
        } catch (IOException e) {           
            e.printStackTrace();
        }
    }

}

Đây là Class handlerClient.java – Mục đích Thread ở đây mình sẻ cho nó ngủ vào 1 tham số Random

package com.gcs.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.Random;

public class HandlerClient implements Runnable{
	Socket socket;
	BufferedReader reader;
	//static Logger logger = Logger.getLogger(HandlerClient.class);
	public HandlerClient(Socket socket) {	
		//PropertyConfigurator.configure("log4j.properties");
		try {
			this.socket = socket;
			reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		} catch (IOException e) {
			e.printStackTrace();
		}   
	}

	public void run() {
		// do something	with sockets
		try {
			String clientSend = reader.readLine();
			while(true){
				// process every thing and out
				int sleepSecond = new Random().nextInt(5000);
				System.out.println(clientSend + " is running...");
				//logger.info(clientSend + " is running...");
				pauseProcessSomeThing(sleepSecond);				
				break; // condition for we known ..Thread worked.
			}
			//logger.info("\t" + clientSend + " is finished...");
			System.err.println("\t" + clientSend + " is finished...");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void pauseProcessSomeThing(int milis){
		try {
			Thread.sleep(milis);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

Nếu ai dùng Log4j để in ra kết quả thì các bạn có thể bỏ đi các comment
Kết quả khi run:
d1

Chúng ta thấy. Bắt đầu là Client 1-2-3-4. Khi [1 -OUT] thì có Thread 5 bước vào.
Khi đó trong Pool của chúng ta sẻ có thread 2-3-4-5 Tiếp tục [3-Out] [6-In] => Pool có 2-4-5-6…so on.
Cuối cùng pool còn lại các thread 6-7-8-10.

Một kết quả khác khi mình run lần 2 cho ai dùng Log4j
d1

Chúc các bạn thành công .

Wait and Notify in java

Hôm nay mình xin giới thiệu đến với các bạn, về cách đơn giản trong việc chia sẻ công việc với nhau thông qua sử dụng Synchronization.

Công việc của mình như sau :

  1. ThreadA có tác vụ là xữ lý logic một vấn đề nào đó.
  2. ThreadB có tác vụ sử lý kết quả của logic trả về.
  3. Cả 2 thread đều hoạt động trên cùng 1 đối tượng.

Cách thức chương trình như sau :

Khi thread A xữ ly vấn đề. nếu vấn đề giải quyết thành công  nó sẻ rơi vào trạng thái chờ (wait) và nó kiu gọi (notify)  thằng threadB và nói rắng.

  • Ê thằng kia tao giải quyết xong vấn đề rồi mày thức dậy và sử dụng nó đi.

Thằng B nghe vậy chạy vào sử dụng kết quả trả về , thao tác gì đó , làm gì đó, v.v.v , và khi Thread B làm xong việc nó sẻ rơi vào trạng thái chờ và nói thằng threadA rằng.

  • Tao giải quyết xong rồi. Mày dậy làm việc tiếp đi.

Cứ như vậy công việc dùng chung 1 đối tượng sẻ dừng khi có một điều kiện nào đó .

Chúng ta xem bài viết dưới đây. Mình tạo ra threadA cho for i . nếu i chia hết 1000 thì mình sẻ gọi thằng thread B show value ra.

Đối tượng dùng chung : MyObject.java

package com.gcs.lockobject;

public class MyObject {
	private boolean valid = false;
	int i = 0;

	public synchronized void showValue(){
		try {			
			while(!isValid()){
				wait();
			}
			//pause();	
			System.out.println(i);
			setValid(false);
			notifyAll();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public synchronized void setValue(int value){
		try {
			while(isValid()){
				wait();
			}
			this.i = value;
			setValid(true);
			notifyAll();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public int getI() {
		return i;
	}

	public void setI(int i) {
		this.i = i;
	}

	public void pause(){
		try {
			Thread.sleep(50);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public boolean isValid() {
		return valid;
	}

	public void setValid(boolean valid) {
		this.valid = valid;
	}

}

Thread A : Xữ lý công việc Logic

package com.gcs.lockobject;

public class ThreadA implements Runnable{
	MyObject object;
	int i = 0;

	public ThreadA(MyObject object) {
		super();
		this.object = object;
	}

	public void run() {		
		for(int i = 1000; i <= 1000000; i++){
			if(i%1000 == 0){
				object.setValue(i);
			}
		}
		System.out.println("Thread A - Finished");
	}

}

Thread B : Xữ lý kết quả Logic Trả về


package com.gcs.lockobject;

public class ThreadB implements Runnable{
	MyObject obj;

	public ThreadB(MyObject obj) {
		this.obj = obj;
	}

	public void run() {		
		while(true){			
			obj.showValue();
			if(obj.i == 1000000)
				break;
		}
		System.out.println("Thread B - Finished");
	}

}

Hàm main của chúng ta

package com.gcs.lockobject;

public class MainTest {
	public static void main(String[] args) {
		MyObject object = new MyObject();

		Thread tA = new Thread(new ThreadA(object));
		Thread tB = new Thread(new ThreadB(object));

		tA.start();
		tB.start();
	}
}

Hy vọng giúp ích cho các bạn !!!!

Network Socket – Part 2

Tiếp theo bài SOCKET basic kia …mình làm 1 bài tương tự nhưng Server có thể giao tiếp với nhiều Client trong tại 1 thời điểm. Tuy vậy cách này vẫn không đảm bảo….vẫn có trường hợp Race khi 2 Client cùng 1 lúc giao tiếp với server. Nhưng đây là cách đơn giản mà chúng ta thể hiển một chương trình . 1 Server – N Client

Client chúng ta như sau :

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class ClientA {
	public static void main(String[] args) {
		// initialize Client and connect to server with port 9999
		ClientA myClient = new ClientA();
		myClient.connectServer("127.0.0.1", 8989);

	}

	public void connectServer(String server, int port){
		try {
			// Make a socket connection to whatever is running on server - port
			Socket s = new Socket(server, port);

			// send data to server
			PrintWriter writer = new PrintWriter(s.getOutputStream(),true);
			String message = "";
			Scanner sc = new Scanner(System.in);
			while(true){
				message = sc.nextLine();
				if(message.equals("close"))
					break;
				writer.println("Client 1 : " + message);
			}
			writer.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
}

Server của chúng ta :

package com.gcs.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class Server {

	public static void main(String[] args) {
		Server myServer = new Server();
		myServer.publicServer();
	}

	public void publicServer(){
		try {
			// ServerSocket make this server application listen for client request
			// on port 4242 while(true) to listening continuous
			ServerSocket serverSocket = new ServerSocket(8989);
			System.out.println("Server start connect.....");
			while(true){
				// listening.....
				Socket sock = serverSocket.accept();
				// we create thread to handler message from client
				Thread t = new Thread(new HandlerClient(sock));
				t.start();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public class HandlerClient implements Runnable{
		BufferedReader reader;
		Socket socketClient;

		// we initialize BufferedReader to get message from client
		public HandlerClient(Socket socketClient) {
			try {
				this.socketClient = socketClient;
				reader = new BufferedReader(new InputStreamReader(socketClient.getInputStream()));

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		// get communication maintain to when mess="close" .
		public void run() {
			String message = "";
			try {
				while(true){
					message = reader.readLine();
					if(!message.equalsIgnoreCase("close")){
						System.out.println(message);

					}
					else{
						System.out.println("Client Close....");
						break;
					}
				}
			} catch (Exception e) {}

		}

	}
}

1 – Chúng ta Start Server lên
2 – Chúng ta mở command line để biên dịch và run client.

kết quả đơn giản chúng ta có thể thấy như sau :
d1

Hy vọng help các chú =]]….

Server communicate with the client – [Socket]

Hôm nay mình hướng dẫn nhanh gọn cách để tạo 1 client – 1 server connect với nhau

package com.gcs.client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {
	public static void main(String[] args) {
		// initialize Client and connect to server with port 9999
		Client myClient = new Client();
		myClient.connectServer("127.0.0.1", 9999);

	}

	@SuppressWarnings("resource")
	public void connectServer(String server, int port){
		try {
			// Make a socket connection to whatever is running on server -  port
			Socket s = new Socket(server, port);

			// set BufferedReader to an InputStreamReader to get inputStream from Socket
			InputStreamReader isReader = new InputStreamReader(s.getInputStream());
			BufferedReader reader = new BufferedReader(isReader);
			// read data sent from server
			String serverMessage = reader.readLine();
			// show message
			System.out.println("Connect Server => Response from Server : "+ serverMessage);
			reader.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
}
package com.gcs.server;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
	public static void main(String[] args) {
		Server myServer = new Server();
		myServer.publicServer();
	}

	@SuppressWarnings("resource")
	public void publicServer(){
		try {
			// ServerSocket make this server application listen for client request 
			// on port 4242 while(true) to listening continuous
			ServerSocket serverSocket = new ServerSocket(9999);
			System.out.println("Server start connect.....");
			while(true){
				// listening.....
				Socket sock = serverSocket.accept();
				// we use the socket connection to make PrintWriter and send String value to client
				PrintWriter writer = new PrintWriter(sock.getOutputStream());
				String strValue = "Hello World";
				writer.println(strValue);
				writer.close();
				System.out.println("Server==> Send data success....");
			}
		} catch (IOException e) {			
			e.printStackTrace();
		}
	}
}
  • Client và Server application giao tiếp với nhau thông qua Socket
  • Mổi một Socket đại diện cho một connection giữa 2 applation. và nó có thể run trên 2 máy tách rời nhau.
  • Mổi Client phải biết được cái IP address ( domain name) và cái cống TCP của server application
  • Cổng TCP ở dạng 16-bit. Các cổng từ 0-1023 là các cổng vững chắc của các services như các cổng HTTP, FTP, SMTP…
  • Chúng ta nên thiết lấp các cổng từ 1024 trở đi
  • Mổi Client khi connect đển server chúng ta thể hiện 1 Socket như sau : Socket s = new Socket(“127.0.0.1”,9999).
  • Mổi một connect , client có thể getInput, getOutput Streams từ Socket này. Đây là 1 dạng cấp thấp của data : sock.getInputStream();
  • Để đọc Text data từ Server. Chúng ta tạo ra BufferedReader với tham số là một InputStreamReader nhận inputSteam từ Socket
  • Để viết data to server , chúng ta tạo ra PrintWriter từ Socket output Stream. và gọi print method để send String to server
  • Server sử dụng Server Socket để chờ đợi ( lắng nghe ) request đến từ Client thông qua Port.
  • Khi serverSocket lấy được Request in sẻ tạo ra Connection với Client.
Chúc các bạn thành công