码迷,mamicode.com
首页 > 编程语言 > 详细

解读JAVA多线程

时间:2016-05-11 08:13:28      阅读:234      评论:0      收藏:0      [点我收藏+]

标签:

解读JAVA多线程

两种不同的实现方式

1、继承Thread类,实现多线程

class hello extends Thread {
    private String name;
    public hello() {
    }
    public hello(String name) {
        this.name = name;
    }
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + "运行  " + i);
        }
    }
}
public static void main(String[] args) {
        hello h1=new hello("A");
        hello h2=new hello("B");
        h1.start();
        h2.start();
    }

2、实现Runnable接口,实现多线程

class hello implements Runnable {
    private String name;
    public hello() {
    }
    public hello(String name) {
        this.name = name;
    }
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + "运行     " + i);
        }
     public static void main(String[] args){
        hello h1=new hello("线程A");
        Thread demo= new Thread(h1);
        hello h2=new hello("线程B");
        Thread demo1=new Thread(h2);
        demo.start();
        demo1.start();
    }
}

其实Thread中的run方法调用的是Runnable接口的run方法,ThreadRunnable都实现了run方法,这种操作模式其实就是代理模式。

3、两种实现方式的区别

如果一个类继承Thread,则不适合实现资源共享。但是如果实现Runnable接口的话,则很容易实现资共享。

class hello extends Thread {
    public void run() {
        for (int i = 5; i >= 0; i--) {
            System.out.println("i = " + i);
        }
    }
    public static void main(String[] args) {
        hello h1 = new hello();
        hello h2 = new hello();
        h1.start();
        h2.start();
    }
}

运行结果为:

i = 5

i = 4

i = 3

i = 2

i = 1

i = 0

i = 5

i = 4

i = 3

i = 2

i = 1

i = 0

如果使用多线程去实现一个卖票的系统,继承Thread的方法就不行了,要用Runnable的实现方式

class MyThread implements Runnable{
    private int ticket = 5;  //5张票
    public void run() {
        for (int i=0; i<=20; i++) {
            if (this.ticket > 0) {
                System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--);
            }
        }
    }
}
public class Test {
    public static void main(String [] args) {
        MyThread my = new MyThread();
        new Thread(my, "1号窗口").start();
        new Thread(my, "2号窗口").start();
    }
}

运行结果为:

1号窗口正在卖票5

1号窗口正在卖票4

2号窗口正在卖票3

1号窗口正在卖票1

1号窗口正在卖票2

总结

实现Runnable比继承Thread更具有的优势:

1、适合多个相同的程序的线程去处理同一个资源。

2、可避免JAVA单继承限制

3、增加程序的健壮性,代码可被多个线程共享,代码和数据独立

【main方法本身也是一个线程,JAVA的垃圾回收机制也是线程,所以程序运行至少会有两个线程运作】

线程的强制执行

class hello implements Runnable {
        public void run() {
            for (int i = 0; i < 3; i++) {
                System.out.println(Thread.currentThread().getName());
            }
        }
        public static void main(String[] args) {
            hello he = new hello();
            Thread thread = new Thread(he,"线程");
            demo.start();
            for(int i=0;i<50;++i){
                if(i>10){
                    try{
                        thread.join();  //强制执行thread
                    }catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("main 线程执行-->"+i);
            }
        }
    }

线程休眠

class hello implements Runnable {
    public void run() {
        for (int i = 0; i < 3; i++) {
            try {
                Thread.sleep(2000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + i);
        }
    }
    public static void main(String[] args) {
        hello he = new hello();
        Thread thread = new Thread(he, "线程");
        thread.start();
    }
}


线程中断

class hello implements Runnable {
    public void run() {
        System.out.println("执行run方法");
        try {
            Thread.sleep(10000);
            System.out.println("线程完成休眠");
        } catch (Exception e) {
            System.out.println("休眠被打断");
            return;  //返回到程序的调用处
        }
        System.out.println("线程正常终止");
    }
    public static void main(String[] args) {
        hello he = new hello();
        Thread thread = new Thread(he, "线程");
        thread.start();
        try{
            Thread.sleep(2000);
        }catch (Exception e) {
            e.printStackTrace();
        }
        thread.interrupt(); //2s后中断线程
    }
}

线程的优先级

class hello implements Runnable {
    public void run() {
        for(int i=0;i<5;++i){
            System.out.println(Thread.currentThread().getName()+"运行"+i);
        }
    }
    public static void main(String[] args) {
        Thread h1=new Thread(new hello(),"A");
        Thread h2=new Thread(new hello(),"B");
        h1.setPriority(8);
        h2.setPriority(2);
        h1.start();
        h2.start();
    }
}

这里注意,并不是优先级越高越先执行,而是看谁先抢到CPU,主线程的优先级为5

线程的礼让

class hello implements Runnable {
    public void run() {
        for(int i=0;i<5;++i){
            System.out.println(Thread.currentThread().getName()+"运行"+i);
            if(i==3){
                System.out.println("线程的礼让");
                Thread.currentThread().yield();//通过yield方法将一个线程的操作暂时交给另一个线程执行
            }
        }
    }
    public static void main(String[] args) {
        Thread h1=new Thread(new hello(),"A");
        Thread h2=new Thread(new hello(),"B");
        h1.start();
        h2.start();
    }
}

线程的同步和死锁

class hello implements Runnable {
    public void run() {
        for(int i=0;i<10;++i){
            if(count>0){
                try{
                    Thread.sleep(1000);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println(count--);
            }
        }
    }
    public static void main(String[] args) {
        hello he=new hello();
        Thread h1=new Thread(he);
        Thread h2=new Thread(he);
        Thread h3=new Thread(he);
        h1.start();
        h2.start();
        h3.start();
    }
    private int count=5;
}

运行结果为:

5

4

3

2

1

0

-1

这里出现了-1,而代码判断了count>0,出现这样的情况是没有用到线程同步

线程同步就是说在同一个时间段中,只有一个线程能运行,其他线程必须等待着个线程结束后才能被执行

class hello implements Runnable {
    public void run() {
        for(int i=0;i<10;++i){
            synchronized (this) {
                if(count>0){
                    try{
                        Thread.sleep(1000);
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }
                    System.out.println(count--);
                }
            }
        }
    }
    public static void main(String[] args) {
        hello he=new hello();
        Thread h1=new Thread(he);
        Thread h2=new Thread(he);
        Thread h3=new Thread(he);
        h1.start();
        h2.start();
        h3.start();
    }
    private int count=5;
}

this 为当前对象,一般吧当前对象作为同步对象

同样也可以采用下面的代码

<div class="line number4 index3 alt1"><code class="java keyword">class</code> <code class="java plain">hello </code><code class="java keyword">implements</code> <code class="java plain">Runnable {</code></div><div class="line number5 index4 alt2"><code class="java spaces">    </code><code class="java keyword">public</code> <code class="java keyword">void</code> <code class="java plain">run() {</code></div><div class="line number6 index5 alt1"><code class="java spaces">        </code><code class="java keyword">for</code> <code class="java plain">(</code><code class="java keyword">int</code> <code class="java plain">i = </code><code class="java value">0</code><code class="java plain">; i < </code><code class="java value">10</code><code class="java plain">; ++i) {</code></div><div class="line number7 index6 alt2"><code class="java spaces">            </code><code class="java plain">sale();</code></div><div class="line number8 index7 alt1"><code class="java spaces">        </code><code class="java plain">}</code></div><div class="line number9 index8 alt2"><code class="java spaces">    </code><code class="java plain">}</code></div><div class="line number11 index10 alt2"><code class="java spaces">    </code><code class="java keyword">public</code> <code class="java keyword">synchronized</code> <code class="java keyword">void</code> <code class="java plain">sale() {</code></div><div class="line number12 index11 alt1"><code class="java spaces">        </code><code class="java keyword">if</code> <code class="java plain">(count > </code><code class="java value">0</code><code class="java plain">) {</code></div><div class="line number13 index12 alt2"><code class="java spaces">            </code><code class="java keyword">try</code> <code class="java plain">{</code></div><div class="line number14 index13 alt1"><code class="java spaces">                </code><code class="java plain">Thread.sleep(</code><code class="java value">1000</code><code class="java plain">);</code></div><div class="line number15 index14 alt2"><code class="java spaces">            </code><code class="java plain">} </code><code class="java keyword">catch</code> <code class="java plain">(InterruptedException e) {</code></div><div class="line number16 index15 alt1"><code class="java spaces">                </code><code class="java plain">e.printStackTrace();</code></div><div class="line number17 index16 alt2"><code class="java spaces">            </code><code class="java plain">}</code></div><div class="line number18 index17 alt1"><code class="java spaces">            </code><code class="java plain">System.out.println(count--);</code></div><div class="line number19 index18 alt2"><code class="java spaces">        </code><code class="java plain">}</code></div><div class="line number20 index19 alt1"><code class="java spaces">    </code><code class="java plain">}</code></div><div class="line number22 index21 alt1"><code class="java spaces">    </code><code class="java keyword">public</code> <code class="java keyword">static</code> <code class="java keyword">void</code> <code class="java plain">main(String[] args) {</code></div><div class="line number23 index22 alt2"><code class="java spaces">        </code><code class="java plain">hello he = </code><code class="java keyword">new</code> <code class="java plain">hello();</code></div><div class="line number24 index23 alt1"><code class="java spaces">        </code><code class="java plain">Thread h1 = </code><code class="java keyword">new</code> <code class="java plain">Thread(he);</code></div><div class="line number25 index24 alt2"><code class="java spaces">        </code><code class="java plain">Thread h2 = </code><code class="java keyword">new</code> <code class="java plain">Thread(he);</code></div><div class="line number26 index25 alt1"><code class="java spaces">        </code><code class="java plain">Thread h3 = </code><code class="java keyword">new</code> <code class="java plain">Thread(he);</code></div><div class="line number27 index26 alt2"><code class="java spaces">        </code><code class="java plain">h1.start();</code></div><div class="line number28 index27 alt1"><code class="java spaces">        </code><code class="java plain">h2.start();</code></div><div class="line number29 index28 alt2"><code class="java spaces">        </code><code class="java plain">h3.start();</code></div><div class="line number30 index29 alt1"><code class="java spaces">    </code><code class="java plain">}</code></div><div class="line number32 index31 alt1"><code class="java spaces">    </code><code class="java keyword">private</code> <code class="java keyword">int</code> <code class="java plain">count = </code><code class="java value">5</code><code class="java plain">;</code></div><div class="line number33 index32 alt2"><code class="java plain">}</code></div>

【当多个线程共享一个资源的时候需要同步,但是过多的同步可能会导致死锁】 


关于wait、sleep和notify方法:

1、线程中wait和sleep最大的不同是在等待时,wait会释放锁,而sleep会一直持有锁wait通常被用于线程间的交互,sleep通常用于暂停执行

2、wait方法能使线程阻塞,调用notify方法能唤醒当前备阻塞的线程

3、如果调用某个对象的wait方法,当前线程必须拥有这个对象的monitor(即锁),因此调用wait方法必须在同步块,或者同步方法中进行

4、调用某个对象的wait方法,相当于让当前线程交出此对象的monitor(即锁),然后进入等待状态,等待后继续获得此对象的锁( sleep方法则是使当前线程暂停执行一段时间,从而让其他线程有机会继续执行,但他并不会释放对象锁)

5、notify方法能够唤醒一个正在等待该对象的monitor的线程,当有多个线程都在等待该对象的monitor的话,则只能唤醒其中一个线程,具体唤醒哪个线程则不得而知

6、调用某个对象的notify方法,当前线程也必须拥有这个对象的monitor,因此调用notify()方法必须在同步块或者同步方法中进行

7、notify和notifyAll方法只是唤醒等待该对象的monitor的线程,并不决定哪个线程能够获取到monitor


解读JAVA多线程

标签:

原文地址:http://blog.csdn.net/wei4487835/article/details/51368134

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!