解读JAVA多线程

解读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方法,Thread和Runnable都实现了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

时间: 2024-10-19 08:26:08

解读JAVA多线程的相关文章

七张图解读Java多线程

七张图解读Java多线程 --by:coder-pig,转载请注明出处~ 本节引言: 如题,笔者把Java多线程一些概念性的东西以及一些基础的东西都归纳到这七张图中,其中囊括 基本的多线程概念,创建线程,线程组,线程池,以及自定义简单的线程池,还附有代码, 大家也可以像笔者一样,把这七张图mark后打印出来,偶尔回味回味~ J2SE多线程 Part 1 J2SE多线程 Part 2 J2SE多线程 Part 3 J2SE多线程 Part 4 J2SE多线程 Part 5 J2SE多线程 Part

全面解读Java NIO工作原理(4)

全面解读Java NIO工作原理(4) 2011-12-14 10:31 Rollen Holt Rollen Holt的博客 我要评论(0) 字号:T | T JDK 1.4 中引入的新输入输出 (NIO) 库在标准 Java 代码中提供了高速的.面向块的 I/O.本实用教程从高级概念到底层的编程细节,非常详细地介绍了 NIO 库.您将学到诸如缓冲区和通道这样的关键 I/O 元素的知识,并考察更新后的库中的标准 I/O 是如何工作的.您还将了解只能通过 NIO 来完成的工作,如异步 I/O 和

两张图解读Java异常与断言

两张图解读Java异常与断言                                 --转载请注明出处:coder-pig 本节引言: 前天发布的"七张图解析Java多线程"大家的反响不错,嗯呢,今天再来两张吧, 关于Java异常与断言的,涉及到的东西有: ①什么是异常,为什么会出现异常,异常处理机制模型,常见异常信息总结,检验异常与非检验异常; 异常的捕获:try-catch块,finally块,多重catch块,try-catch块的嵌套; 异常的声明:throws回避异

Java基础10:全面解读Java异常

Java基础10:全面解读Java异常 为什么要使用异常 首先我们可以明确一点就是异常的处理机制可以确保我们程序的健壮性,提高系统可用率.虽然我们不是特别喜欢看到它,但是我们不能不承认它的地位,作用. 在没有异常机制的时候我们是这样处理的:通过函数的返回值来判断是否发生了异常(这个返回值通常是已经约定好了的),调用该函数的程序负责检查并且分析返回值.虽然可以解决异常问题,但是这样做存在几个缺陷: 1. 容易混淆.如果约定返回值为-11111时表示出现异常,那么当程序最后的计算结果真的为-1111

Java基础9:解读Java回调机制

Java基础9:解读Java回调机制 模块间的调用 本部分摘自https://www.cnblogs.com/xrq730/p/6424471.html 在一个应用系统中,无论使用何种语言开发,必然存在模块之间的调用,调用的方式分为几种: (1)同步调用 同步调用是最基本并且最简单的一种调用方式,类A的方法a()调用类B的方法b(),一直等待b()方法执行完毕,a()方法继续往下走.这种调用方式适用于方法b()执行时间不长的情况,因为b()方法执行时间一长或者直接阻塞的话,a()方法的余下代码是

Java多线程系列--“JUC锁”11之 Semaphore信号量的原理和示例

概要 本章,我们对JUC包中的信号量Semaphore进行学习.内容包括:Semaphore简介Semaphore数据结构Semaphore源码分析(基于JDK1.7.0_40)Semaphore示例 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3534050.html Semaphore简介 Semaphore是一个计数信号量,它的本质是一个"共享锁". 信号量维护了一个信号量许可集.线程可以通过调用acquire()来获取信号量的许可

从JAVA多线程理解到集群分布式和网络设计的浅析

对于JAVA多线程的应用非常广泛,现在的系统没有多线程几乎什么也做不了,很多时候我们在何种场合如何应用多线程成为一种首先需要选择的问题,另外关于java多线程的知识也是非常的多,本文中先介绍和说明一些常用的,在后续文章中如果有必要再说明更加复杂的吧,本文主要说明多线程的一下几个内容: 1.在应用开发中什么时候选择多线程? 2.多线程应该注意些什么? 3.状态转换控制,如何解决死锁? 4.如何设计一个具有可扩展性的多线程处理器? 5.多线程联想:在多主机下的扩展-集群? 6.WEB应用的多线程以及

java多线程心得

多并发的时候,在什么情况下必须加锁?如果不加锁会产生什么样的后果. 加锁的场景跟java的new thread和Runnable的关系是什么? 看看java的concurrentMap源码. 还有spring 的web.xml启动执行源码 spring aop http://www.cnblogs.com/FDROSE1001/p/3661895.html activemq的本质是什么? java的jms hibernate由配置文件映射到实体类的本质是什么? java反射 spring aop

Rhythmk 一步一步学 JAVA (21) JAVA 多线程

1.JAVA多线程简单示例 1.1 .Thread  集成接口 Runnable 1.2 .线程状态,可以通过  Thread.getState()获取线程状态: New (新创建) Runnable (可以运行) Blocked  (被阻塞) Waiting  (等待) Timed waiting (计时等待) Terminated  (被终止) ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27