How to use Thread

1. how to use thread

Two things need to know: Thread class and Runnable interface.

We can instanciate a thread class to be a thread, we can also create a normal class and let this class implements Runnable interface to make it a thread. Because thread class itself also has implemented the Runnable interface. Both of them have to overwrite the run() method which is inherited from Runnable interface.

2. the first way: using Thread class

In this way, we need to declare a class to be a subclass of Thread. This subclass should override therun method of classThread. An instance of the subclass can then be allocated and started. For example, a thread that computes primes larger than a stated value could be written as follows:

     class PrimeThread extends Thread {
         long minPrime;
         PrimeThread(long minPrime) {
             this.minPrime = minPrime;
         }
        /**this constructor is defined by the user and is more convenient,like this way
         * we need to count the minimum prime number, we can use this constructor to pass
         * the unmber we need and to handle it in the run() method.
        **/
     public void run() {
             // compute primes larger than minPrime
              . . .
         }
     }

the following code is the way to start the thread:

  PrimeThread p = new PrimeThread(143);
     p.start();

3. the seccond way: normal class implement the runnable interface

The other way to create a thread is to declare a class that implements the Runnable interface. That class then implements the run method. An instance of the class can then be allocated, passed as an argument when creatingThread, and started. The same example in this other style looks like the following:

     class PrimeRun implements Runnable {
         long minPrime;
         PrimeRun(long minPrime) {
             this.minPrime = minPrime;
         }
 
         public void run() {
             // compute primes larger than minPrime
              . . .
         }
     }

the following code is the way to create the thread and start it

PrimeRun p = new PrimeRun(143);
     new Thread(p).start();

here we usethe class PrimeRun as an parameter of the Thread class. we can have a look at the constructor of the Thread class in the API

we have a class p which has implemented Runnable interface, here we pass it as an parameter of Runnable, so Thread(p).start() acctually calls p's run() method and can only call this one method. As we can see there is a Polimorphism here, and we know the run() method called is the one overwrited in class p not the one in its super class Runnable.


4. sleep()

import java.util.*;
public class TestInterrupt {
  public static void main(String[] args) {
    MyThread thread = new MyThread();
    thread.start();
    try {Thread.sleep(10000);}
    //this means the main thread will sleep 10 seconds
    catch (InterruptedException e) {}
    thread.interrupt();
    //interrupt the main thread,which will also make mythread interruptted
   }
}

class MyThread extends Thread {
	boolean flag = true;
  public void run(){
    while(flag){
      System.out.println("==="+new Date()+"===");
      try {
        sleep(1000);
       //we can use Thread.sleep(1000) if MyThread implements Runnable
      } catch (InterruptedException e) {
        return;
      }
    }
  }
}


5.Synchronized key word

If there is a synchronized method m1(), and there are 2 thread running, both of which can call the m1 mehtod, synchronized promise that at the same time there is only one thread can call this method.

see this two examples blew: 

Example 1

package com.thread;

public class TT implements Runnable {
	int b = 100;
	
	public synchronized void m1() throws Exception{
		b = 1000;
		Thread.sleep(5000);
		System.out.println("b = " + b);
	}
	
	public void m2() throws Exception {
		Thread.sleep(2500);
		b = 2000;
	}
	
	public void run() {
		try {
			m1();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) throws Exception {
		TT tt = new TT();
		Thread t = new Thread(tt);
		t.start();
		/** t.start() doesn't means that the thread t is now executing, it only let t
		 * goes to the "ready" stage, so we need add Thread.sleep(1000) below to make
		 * the main thread sleep and the thread t will go from "ready" to "start"
		 */
		Thread.sleep(1000);
		tt.m2();
		System.out.println(tt.b);
	}
}
result:   2000           b=2000


In the main method, t.start() doesn't means that the thread t is now executing, it only let t goes to the "ready" stage, so we need add Thread.sleep(1000) below to makethe main thread sleep and the thread t will go from "ready" to "start". So it goes into synchronized m1(), in m1, it changed b to 1000 and it went into sleep. During its sleep, main thread wake up and calls m2(), in m2 method it needs to change b's value to 2000. Even though at this tiime m1 is not finished, and b is now locked by m1(), m2 method cal still change the value of b. so it changed b's value to 2000. The main thread printed out b's vaue: 2000 and m1 wake up and print: b=2000.

At this point, we can see the key word doesn't fullfill its responsibility. what we want is even though m1 is sleeping now we want m2 wait until m1 has printed out b's value.

example 2

package com.thread;

public class TT implements Runnable {
	int b = 100;
	
	public synchronized void m1() throws Exception{
		b = 1000;
		Thread.sleep(5000);
		System.out.println("b = " + b);
	}
	
	public synchronized void m2() throws Exception {
		Thread.sleep(2500);
		b = 2000;
	}
	
	public void run() {
		try {
			m1();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) throws Exception {
		TT tt = new TT();
		Thread t = new Thread(tt);
		t.start();
		/** t.start() doesn't means that the thread t is now executing, it only let t
		 * goes to the "ready" stage, so we need add Thread.sleep(1000) below to make
		 * the main thread sleep and the thread t will go from "ready" to "start"
		 */
		Thread.sleep(1000);
		tt.m2();
		System.out.println(tt.b);
	}
}
output:    b=1000           2000


In example 2, we only added the key word "synchronized " for m2. In this way when m1 is sleeping tt.m2() won't execute because both of them are synchronized m2 has too wait until m1 wake up and finished its work. We may think: is it because both m1 and m2 are locking b, since m1 was called before m2, so m2 has to wait ? what about the object m2 is locking c not b?

example 3:


package com.thread;

public class TT implements Runnable {
	int b = 100;
	int c = 20;
	
	public synchronized void m1() throws Exception{
		b = 1000;
		Thread.sleep(5000);
		System.out.println("b = " + b);
	}
	
	public synchronized void m2() throws Exception {
		//Thread.sleep(2500);
		c = 2000;
		System.out.println("c = " + c);
	}
	
	public void run() {
		try {
			m1();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) throws Exception {
		TT tt = new TT();
		Thread t = new Thread(tt);
		t.start();
		/** t.start() doesn't means that the thread t is now executing, it only let t
		 * goes to the "ready" stage, so we need add Thread.sleep(1000) below to make
		 * the main thread sleep and the thread t will go from "ready" to "start"
		 */
		Thread.sleep(1000);
		tt.m2();
		System.out.println(tt.b);
	}
}

In this way, m2 locks c , m1 locks b, they are not disturbing each other, but still, m2 need to wait  until m1 wake up and finshes its work.


6.producer and consumer(   wait() and notify()  )

package com.thread;
public class ProducerConsumer {
	public static void main(String[] args) {
		SyncStack ss = new SyncStack();
		Producer p = new Producer(ss);
		Consumer c = new Consumer(ss);
		new Thread(p).start();
		new Thread(p).start();
		new Thread(p).start();
		new Thread(c).start();
	}
}

class WoTou {
	int id; 
	WoTou(int id) {
		this.id = id;
	}
	public String toString() {
		return "WoTou : " + id;
	}
}

class SyncStack {
	int index = 0;
	WoTou[] arrWT = new WoTou[6];
	
	public synchronized void push(WoTou wt) {
		while(index == arrWT.length) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notifyAll();		
		arrWT[index] = wt;
		index ++;
	}
	
	public synchronized WoTou pop() {
		while(index == 0) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notifyAll();
		index--;
		return arrWT[index];
	}
}

class Producer implements Runnable {
	SyncStack ss = null;
	Producer(SyncStack ss) {
		this.ss = ss;
	}
	
	public void run() {
		for(int i=0; i<20; i++) {
			WoTou wt = new WoTou(i);
			ss.push(wt);
System.out.println("生产了:" + wt);
			try {
				Thread.sleep((int)(Math.random() * 200));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}			
		}
	}
}

class Consumer implements Runnable {
	SyncStack ss = null;
	Consumer(SyncStack ss) {
		this.ss = ss;
	}
	
	public void run() {
		for(int i=0; i<20; i++) {
			WoTou wt = ss.pop();
System.out.println("消费了: " + wt);
			try {
				Thread.sleep((int)(Math.random() * 1000));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}			
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值