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...
本文出自 “阿凡达” 博客,请务必保留此出处http://shamrock.blog.51cto.com/2079212/1410738