1.简单Java多线程例子(继承Thread)

public class hello extends Thread{    private String name;                                                                                                                                                                                                                                                                                                                                                           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 hello1 = new hello("A");        hello hello2 = new hello("B");        hello hello3 = new hello("C");        hello1.start();        hello2.start();        hello3.start();    }}

某一次的执行结果为:

B运行...0

B运行...1

B运行...2

C运行...0

A运行...0

C运行...1

B运行...3

C运行...2

A运行...1

C运行...3

B运行...4

C运行...4

A运行...2

A运行...3

A运行...4

2.简单Java多线程例子(实现Runnable接口)

public class Test1 implements Runnable {//实现Runnable接口    private String name;    public Test1(String name) {        this.name = name;    }    @Override    public void run() {        for (int i = 0; i < 5; i++) {            System.out.println(name + "运行..." + i);        }    }                                                                                                                                                                                                                                                                                                                                        public static void main(String[] args) {        Test1 test1 = new Test1("线程A");        Thread demo = new Thread(test1);        Test1 test2 = new Test1("线程B");        Thread demo1 = new Thread(test2);        Test1 test3 = new Test1("线程C");        Thread demo2 = new Thread(test3);                                                                                                                                                                                                                                                                                                                                                demo.start();        demo1.start();        demo2.start();    }}

某一次的执行结果为

线程A运行...0

线程A运行...1

线程A运行...2

线程B运行...0

线程B运行...1

线程A运行...3

线程C运行...0

线程A运行...4

线程B运行...2

线程B运行...3

线程C运行...1

线程B运行...4

线程C运行...2

线程C运行...3

线程C运行...4

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

Thread和Runnable的区别:

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

如果是一个买票系统,如果count表示的是车票的数量,使用Runnable接口

public class MyThread implements Runnable{    private int ticket = 5;    @Override    public void run() {        for (int i = 0; i < 20; i++) {            if (this.ticket > 0) {                System.out.println(Thread.currentThread().getName() + "正在买票" + this.ticket--);//              this.ticket--;//不可以分开写,线程级别,会出现不同步...            }        }    }}
public static void main(String[] args) {    MyThread mt = new MyThread();    new Thread(mt, "1号窗口").start();    new Thread(mt, "2号窗口").start();    new Thread(mt, "3号窗口").start();}

某一次的执行结果为

1号窗口正在买票5

3号窗口正在买票3

2号窗口正在买票4

3号窗口正在买票1

1号窗口正在买票2

总结:

实现Runnable接口比继承Thread类所具有的优势:

1):适合多个相同的程序代码的线程去处理同一个资源

2):可以避免java中的单继承的限制

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

建议尽量使用Runnable接口

public class Test3 implements Runnable {    @Override    public void run() {        for (int i = 0; i < 3; i++) {            System.out.println(Thread.currentThread().getName());        }    }    public static void main(String[] args) {        Test3 test = new Test3();        new Thread(test, "A").start();        new Thread(test, "B").start();        new Thread(test).start();    }}

某一次的执行结构为

A

B

B

B

Thread-0

Thread-0

A

A

Thread-0

如果我们没有指定名字的话,系统自动提供名字。

提醒一下大家:main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。

在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个JVM实习在就是在操作系统中启动了一个进程。

判断线程是否启动

public class Test4 implements Runnable {    @Override    public void run() {        for (int i = 0; i < 3; i++) {            System.out.println(Thread.currentThread().getName());        }    }    public static void main(String[] args) {        Test4 test = new Test4();        Thread demo = new Thread(test);        System.out.println("线程启动之前---》" + demo.isAlive());        demo.start();        System.out.println("线程启动之后---》" + demo.isAlive());    }}

某一次的执行结果为

线程启动之前---》false

线程启动之后---》true

Thread-0

Thread-0

Thread-0

主线程也有可能在子线程结束之前结束。并且子线程不受影响,不会因为主线程的结束而结束。

线程的强制执行

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

某一次的执行结果为

main 线程执行-->0

线程

线程

线程

线程

线程

线程

线程

线程

线程

线程

main 线程执行-->1

main 线程执行-->2

main 线程执行-->3

main 线程执行-->4

main 线程执行-->5

main 线程执行-->6

main 线程执行-->7

main 线程执行-->8

main 线程执行-->9

线程的休眠

public class Test6 implements Runnable {    @Override    public void run() {        for (int i = 0; i < 3; i++) {            try {                System.out.println(new Date());                Thread.sleep(2000);//休眠2000毫秒                System.out.println(new Date());            } catch (Exception e) {                e.printStackTrace();            }            System.out.println(Thread.currentThread().getName() + i);        }    }    public static void main(String[] args) {        Test6 t = new Test6();        Thread demo = new Thread(t, "线程");        demo.start();    }}

某一次的执行结果

Thu May 15 15:01:11 CST 2014

Thu May 15 15:01:13 CST 2014

线程0

Thu May 15 15:01:13 CST 2014

Thu May 15 15:01:15 CST 2014

线程1

Thu May 15 15:01:15 CST 2014

Thu May 15 15:01:17 CST 2014

线程2

线程的中断

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

某一次的执行结果

执行run方法

Thu May 15 15:05:04 CST 2014

Thu May 15 15:05:06 CST 2014

休眠被打断

守护线程

public class Test8 implements Runnable{    public void run() {        while (true) {            System.out.println(Thread.currentThread().getName() + "在运行");        }    }    public static void main(String[] args) throws InterruptedException {        Test8 t = new Test8();        Thread demo = new Thread(t, "线程");        demo.setDaemon(true);//守护线程:守护线程则是用来服务用户线程的//如果没有其他用户线程在运行,那么就没有可服务对象,也就没有理由继续下去。        demo.start();        System.out.println("Hello world!!!");    }}

执行结果

Hello world!!!

线程在运行

线程在运行

线程在运行

线程在运行

线程在运行

如果没有System.out.println("Hello world!!!");这句,run方法里面的语句不会执行

线程的优先级

public class Test9 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 Test9(), "A");        Thread h2 = new Thread(new Test9(), "B");        Thread h3 = new Thread(new Test9(), "C");        h1.setPriority(8);        h2.setPriority(2);        h3.setPriority(6);        h1.start();        h2.start();        h3.start();    }}

某一次的执行结果

A运行0

A运行1

A运行2

B运行0

C运行0

B运行1

A运行3

B运行2

C运行1

B运行3

A运行4

B运行4

C运行2

C运行3

C运行4

谁先执行还是取决于谁先去的CPU的资源,主线程的优先级是5

线程的礼让

在线程操作中,也可以使用yield()方法,将一个线程的操作暂时交给其他线程执行

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

某一次的执行结果

A运行0

B运行0

B运行1

A运行1

B运行2

线程的礼让

B运行3

B运行4

A运行2

线程的礼让

A运行3

A运行4

线程同步

在买票的程序中需要考虑线程同步保证数据不出错

格式

synchronized(同步对象){                                                                                   //需要同步的代码                                                                                  }

public class Test11 implements Runnable {    private int count = 5;    @Override    public void run() {        for (int i = 0; i < 10; ++i) {            synchronized (this) {//线程同步                if (count > 0) {                    try {                        Thread.sleep(1000);                    } catch (Exception e) {                        e.printStackTrace();                    }                    System.out.println(count--);                }            }        }    }    public static void main(String[] args) {        Test11 t = new Test11();        Thread thread1 = new Thread(t);        Thread thread2 = new Thread(t);        Thread thread3 = new Thread(t);        thread1.start();        thread2.start();        thread3.start();    }}

执行结果

5

4

3

2

1

每秒钟输一个

也可以采用同步方法

语法格式为

synchronized 方法返回类型方法名(参数列表){                                                              // 其他代码                                                          }

采用同步方法解决上面的问题

public class Test12 implements Runnable {    private int count = 5;    @Override    public void run() {        for (int i = 0; i < 10; i++) {            sale();        }    }    public synchronized void sale() {// 同步方法        if (count > 0) {            try {                Thread.sleep(1000);            } catch (Exception e) {                e.printStackTrace();            }            System.out.println(count--);        }    }                                                          public static void main(String[] args) {        Test12 t = new Test12();        Thread thread1 = new Thread(t);        Thread thread2 = new Thread(t);        Thread thread3 = new Thread(t);                                                                  thread1.start();        thread2.start();        thread3.start();    }}

执行效果和上面的同步线程完全一样。

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

经典的生产者和消费者问题············To be continued...