线程

实现的方式

实现的方式有两种,一种为继承Thread类

public   class  ThreadTestExtends  extends  Thread {

    
public static void main(String[] args){
        
new ThreadTestExtends().start();
        
new ThreadTestExtends().start();
    }

    
    
public void run(){
        
for(int i = 1; i<=10; i++){
            System.out.println(i);
        }

    }

}

另外一种为实现Runnable接口

public   class  ThreadTestRunnable  implements  Runnable {
    
    
public static ThreadTestRunnable a1 = new ThreadTest();
    
public static Thread t1 = new Thread(a1);
    
    
public static ThreadTestRunnable a2 = new ThreadTest();
    
public static Thread t2 = new Thread(a2);
    
    
public static void main(String[] args){        
        t1.start();
        t2.start();
    }

    
    
public void run(){
        
for(int i = 1; i<=10;i++){
            System.out.println(i);
        }

    }

    
    
}

两种方式的主要区别在于:
1,Runnable接口方式给自己的类带来更大的灵活性(多继承)。
2,第一种方式由于是继承了Thread类,所以有几个线程就需要创建多少个对象。
       第二种方式可以就同一对象创建多个线程。
建议使用Runnable接口方式。

synchronized关键字

synchronized用于保护共享数据。它使得多线程的运行结果得到很好的控制。
这里的共享数据指的是 同一个对象不同线程的共享数据。 它并不能控制不同对象不同线程的数据。

public   class  TestSync  implements  Runnable  {

    
public static void main(String[] args) {
        TestSync s1 
= new TestSync();
        TestSync s2 
= new TestSync();

        Thread t1 
= new Thread(s1);
        
// 这里数据并没有死锁,因为是两个不同对象的线程
        Thread t2 = new Thread(s2);
        
// 这里的数据被死锁保护,因为是同一个对象的不同线程
        Thread t3 = new Thread(s1);

        t1.start();
        t2.start();
        t3.start();
    }


    
public void run() {
        
synchronized (this{
            
for (int i = 1; i <= 100; i++{
                System.out.println(
Thread.currentThread().getName() + " : " + i );
            }

        }


    }

}


再看一个例子


public   class  TestSync2  implements  Runnable {
    
    
public static void main(String[] args){
        TestSync2 sample 
= new TestSync2();
        Thread t1 
= new Thread(sample);
        Thread t2 
= new Thread(sample);
        
        t1.start();
        t2.start();
        
    }

    
    
public void run(){
        
for(int i = 1; i<=200; i++){
            System.out.println(Thread.currentThread().getName() 
+ " no synchronised : " + i);
        }

         
        
synchronized(this){
            
for(int i = 1; i<=200;i++){
                System.out.println(Thread.currentThread().getName() 
+ " synchronised : " + i);
            }

        }

        
    }

}

这里又有一点小问题。如果你是使用继承Thread的方式,由于是创建了多个对象,所以对共享数据的控制并不理想。

public   class  TestSync3  extends  Thread  {
    
int i = 0;

    
public static void main(String[] args) {
        TestSync3 t1 
= new TestSync3();
        TestSync3 t2 
= new TestSync3();

        t1.start();
        t2.start();
    }


    
public synchronized void t1() {
        i 
= ++i;
        
try {
            Thread.sleep(
500);
        }
 catch (Exception e) {
        }

        
// 每个线程都进入各自的t1()方法,分别打印各自的i
        System.out.println(Thread.currentThread().getName() + " " + i);
    }


    
public void run() {
        
synchronized (this{
            
for (int k = 1; k <= 10; k++{
                t1();
            }

        }


    }

这里每个线程都只管自己的 i。要实现i共享的话,要将变量和方法改为static

static   int  i  =   0 ;
。。。。。。。。。
  
public   synchronized   static   void  t1() 

sleep()


sleep()会使当前线程暂停执行一段时间。

public   class  TestSleep  implements  Runnable {

    
public static void main(String[] args){
        TestSleep sample 
= new TestSleep();
        
new Thread(sample).start();
    }

    
    
public void run(){
        
for(int i = 1; i<=10; i++){
            
if(i==5){
                
try{
                    Thread.sleep(
5000);
                }
catch(Exception e){
                    e.printStackTrace();
                }

            }

            System.out.print(
" " + i);
        }

    }

}

再来看看下面的例子


public   class  TestSleepPriority  implements  Runnable {
    
        
public static void main(String[] args){
            TestSleepPriority sample 
= new TestSleepPriority();
            Thread t1 
= new Thread(sample);
            Thread t2 
= new Thread(sample);
            t1.setPriority(Thread.MAX_PRIORITY);
            t2.setPriority(Thread.MIN_PRIORITY);
            t1.start();
            t2.start();
        }

        
        
public void run(){
            
            
for(int i = 1; i<=10; i++){
                
if(i==5){
                    
try{
                        Thread.sleep(
5000);
                    }
catch(Exception e){
                        e.printStackTrace();
                    }

                }

                System.out.println(Thread.currentThread().getName() 
+ " : " + i);
            }

        }

}


t1被设置了最高的优先级,t2为最低的优先级。如果没有sleep(5000)的话,那么t2要等到t1结束后再运行。但是由于t1暂停了5秒,所以t2有可能提前执行。如果我们设置了synchronized的话,情况又不一样。

public   class  TestSleepPrioritySync  implements  Runnable  {

    
public static void main(String[] args) {
        TestSleepPrioritySync sample 
= new TestSleepPrioritySync();
        Thread t1 
= new Thread(sample);
        Thread t2 
= new Thread(sample);
        t1.setPriority(Thread.MAX_PRIORITY);
        t2.setPriority(Thread.MIN_PRIORITY);
        t1.start();
        t2.start();
    }


    
public void run() {
        
synchronized (this{
            
for (int i = 1; i <= 10; i++{
                
if (i == 5{
                    
try {
                        Thread.sleep(
5000);
                    }
 catch (Exception e) {
                        e.printStackTrace();
                    }

                }

                System.out
                        .println(Thread.currentThread().getName() 
+ " : " + i);
            }

        }

    }

}

线程在sleep的时候是不会释放锁的。

join()

如果一个线程调用另一个线程的join(),例如t.join()。那么当线程t结束后,主线程才能继续进行。


public   class  TestJoin  implements  Runnable {
    
public static int a = 0;
    
public static void main(String[] args){
        TestJoin sample 
= new TestJoin();
        Thread t 
= new Thread(sample);
        t.start();
        System.out.print(a);
    }

    
    
public void run(){
        
for(int i = 0; i<100; i++){
            a
++;
        }

    }


}


上面的例子里,并不能保证每次都能让结果为100。为什么呢?当运行到t.start()的时候,线程t开始运行,但是main()方法的主线程并没有停止,它还在继续往下运行,这个时候a为什么值就打印什么值。怎么样确保得到100呢?
public   class  TestJoin  implements  Runnable {

    
public static int a = 0;

    
public static void main(String[] args) throws InterruptedException{
        TestJoin sample 
= new TestJoin();
        Thread t 
= new Thread(sample);
        t.start();
        t.join();
        System.out.print(a);
    }

    
    
public void run(){
        
for(int i = 0; i<100; i++){
            a
++;
        }

    }


}

补充:join()方法会抛异常。

yield()

与sleep()相似,但是不能指定暂停时间。并且只能让同优先级的线程得到执行的机会。

public   class  TestYield  implements  Runnable  {

    
public static void main(String[] args) {
        TestYield sample 
= new TestYield();
        Thread t1 
= new Thread(sample, "t1");
        Thread t2 
= new Thread(sample, "t2");
        t1.setPriority(Thread.MAX_PRIORITY);
        t2.setPriority(Thread.MIN_PRIORITY);
        t1.start();
        t2.start();
    }


    
public void run() {

        
for (int i = 1; i <= 10; i++{
            
if (i== 5 && Thread.currentThread().getName().equals("t1")) {
                Thread.yield();
            }

            System.out.println(Thread.currentThread().getName() 
+ " : " + i);
        }

    }

}


wait(), notify(), notifyAll()

与sleep()不同,他们只能在synchronized方法或者是synchronized段中使用,否则运行时会抛异常。

经典的生产者消费者问题:

/**
 * 生产者消费者问题
 * 
 * 
@author chengyumin
 * 
 
*/

public   class  ProdecerConsumer  {
    
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(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.notify();
        arrWT[index] 
= wt;
        index
++;
    }


    
public synchronized WoTou pop() {
        
while (index == 0{
            
try {
                
this.wait();
            }
 catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

        
this.notify();
        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() * 1000));
            }
 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();
            }

        }


    }


}


死锁

/**
 * 测试死锁
 * 
@author chengyumin
 *
 */

public   class  TestDeadLock  implements  Runnable {
    
public int flag = 1;
    
static Object o1 = new Object();
    
static Object o2 = new Object();
    
    
public void run(){
        System.out.println(
"flag = " + flag);
        
        
if(flag == 1){
            
synchronized(o1){
                
try{
                    Thread.sleep(
500);
                }
catch(Exception e){
                    e.printStackTrace();
                }

                
synchronized(o2){
                    System.out.println(
"1");
                }

            }

        }

        
        
if(flag == 0){
            
synchronized(o2){
                
try{
                    Thread.sleep(
500);
                }
catch(Exception e){
                    e.printStackTrace();
                }

                
synchronized(o1){
                    System.out.println(
"0");
                }

            }

        }

    }

    
    
public static void main(String[] args){
        TestDeadLock td1 
= new TestDeadLock();
        TestDeadLock td2 
= new TestDeadLock();
        
        td1.flag 
= 1;
        td2.flag 
= 0;
        
        Thread t1 
= new Thread(td1);
        Thread t2 
= new Thread(td2);
        
        t1.start();
        t2.start();
    }


}


===================================================================================


 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值