继承Thread类实现多线程的步骤:
package com.test.java; /** * 测试通过继承Thread类实现多线程 * @author 林 * */ public class TestJava { public static void main(String[] args) { TestThread t1=new TestThread(); t1.start(); TestThread t2=new TestThread(); t2.start(); } } class TestThread extends Thread { public void run() { //实现run方法 for(int i=0;i<10;i++) { System.out.println(this.getName()+":"+i); //getName()返回线程名称 } } }
输出结果:
Thread-1:0
Thread-1:1
Thread-1:2
Thread-1:3
Thread-0:0
Thread-1:4
Thread-1:5
Thread-1:6
Thread-0:1
Thread-1:7
Thread-1:8
Thread-1:9
Thread-0:2
Thread-0:3
Thread-0:4
Thread-0:5
Thread-0:6
Thread-0:7
Thread-0:8
Thread-0:9
此种方式的缺点:如自定义类已经继承了一个类(如小程序必须继承自Applet类),则无法再继承 Thread 类。
自定义类在实现Runnable接口的同时还可以继承某个类。
在开发中,应用更多的是通过Runnable接口实现多线程。
package com.test.java; /** * 测试通过Runnable接口实现多线程 * @author 林 * */ public class TestJava { public static void main(String[] args) { //创建线程对象,把实现了Runnable接口的对象作为参数传入 Thread t1=new Thread(new TestThread()); t1.start(); Thread t2=new Thread(new TestThread()); t2.start(); } } class TestThread implements Runnable { public void run() { //实现run方法 for(int i=0;i<10;i++) { System.out.println(Thread.currentThread().getName()+":"+i); } } }
输出结果:
Thread-0:0
Thread-1:0
Thread-1:1
Thread-1:2
Thread-0:1
Thread-0:2
Thread-1:3
Thread-1:4
Thread-1:5
Thread-0:3
Thread-1:6
Thread-0:4
Thread-1:7
Thread-0:5
Thread-0:6
Thread-0:7
Thread-0:8
Thread-0:9
Thread-1:8
Thread-1:9
线程生命周期内,经历5个状态:
终止线程通常的做法是提供一个boolean型的终止变量,当这个变量置为false,则终止线程的运行。
package com.test.java; /** * 测试终止线程 * @author 林 * */ public class TestJava { public static void main(String[] args) { TestThread tt1=new TestThread("线程A"); Thread t1=new Thread(tt1); t1.start(); for(int i=0;i<100;i++) { System.out.println("线程B:"+i); } tt1.terminate(); //调用自定义停止方法 System.out.println("线程A停止"); } } class TestThread implements Runnable { String name; boolean live=true; // 标记变量,表示线程是否可中止 public TestThread(String name) { super(); this.name=name; } public void run() { int i=0; while(live) { System.out.println(name+(i++)); } } public void terminate() { //自定义线程停止方法 live=false; } }
输出结果:
...
线程B:91
线程B:92
线程B:93
线程B:94
线程B:95
线程B:96
线程B:97
线程B:98
线程B:99
线程A18
线程A停止
暂停线程执行常用的方法有sleep()和yield()方法,这两个方法的区别是:
package com.test.java; /** * 测试暂停线程sleep()方法 * @author 林 * */ public class TestJava { public static void main(String[] args) { TestThread t1=new TestThread(); t1.start(); TestThread t2=new TestThread(); t2.start(); } } class TestThread extends Thread { public void run() { for(int i=0;i<10;i++) { System.out.println(getName()+":"+i); try { Thread.sleep(2000); //暂停线程2s }catch(InterruptedException e) { e.printStackTrace(); } } } }
package com.test.java; /** * 测试暂停线程yield()方法 * @author 林 * */ public class TestJava { public static void main(String[] args) { TestThread t1=new TestThread(); t1.start(); TestThread t2=new TestThread(); t2.start(); } } class TestThread extends Thread { public void run() { for(int i=0;i<10;i++) { System.out.println(getName()+":"+i); Thread.yield(); //调用yield方法,让出CPU使用权 } } }
线程A在运行期间,可以调用线程B的join()方法,让线程B和线程A联合。这样,线程A就必须等待线程B执行完毕后,才能继续执行。
package com.test.java; /** * 测试线程联合join()方法 * @author 林 * */ public class TestJava { public static void main(String[] args) { Thread a=new Thread(new AThread()); a.start(); } } class AThread implements Runnable { public void run() { System.out.println("A线程开始运行"); System.out.println("A线程请求B线程"); Thread b=new Thread(new BThread()); b.start(); try { b.join(); //调用join方法,必须等B线程执行完成,才执行A线程后面代码 }catch(InterruptedException e) { e.printStackTrace(); } System.out.println("A线程运行完成"); } } class BThread implements Runnable { public void run() { System.out.println("B线程开始运行"); try { System.out.println("B线程运行中"); Thread.sleep(2000); }catch(InterruptedException e) { e.printStackTrace(); } System.out.println("B线程运行完成"); } }
输出结果:
A线程开始运行
A线程请求B线程
B线程开始运行
B线程运行中
B线程运行完成
A线程运行完成
Thread方法:
package com.test.java; /** * 测试Thread常用方法 * @author 林 * */ public class TestJava { public static void main(String[] args) throws InterruptedException { Runnable r=new MyThread(); Thread t=new Thread(r,"Test"); t.start(); System.out.println(t.getName()); //获取线程名称 Thread.currentThread().sleep(2000); //线程暂停2s System.out.println(t.isAlive()); //判断线程还在运行 System.out.println("Over!"); } } class MyThread implements Runnable{ public void run() { for(int i=0;i<10;i++) { System.out.println(i); } } }
输出结果:
Test
0
1
2
3
4
5
6
7
8
9
false
Over!
注意:优先级低只是意味着获得调度的概率低,并不是绝对先调用优先级高的线程后调用优先级低的线程。
package com.test.java; /** * 测试线程优先级 * @author 林 * */ public class TestJava { public static void main(String[] args) throws InterruptedException { Thread t1=new Thread(new MyThread(),"t1"); //设置线程名为t1 Thread t2=new Thread(new MyThread(),"t2"); t1.setPriority(1); //设置线程优先级 t2.setPriority(10); t1.start(); t2.start(); } } class MyThread extends Thread{ public void run() { for(int i=0;i<100;i++) { System.out.println(Thread.currentThread().getName()+":"+i); } } }
输出结果:
...
t1:91
t2:96
t2:97
t1:92
t2:98
t1:93
t2:99
t1:94
t1:95
t1:96
t1:97
t1:98
t1:99
线程同步:多个需要同时访问此对象的线程进入这个对象的等待池形成队列,等待前面的线程使用完毕后,下一个线程再使用。
Java通过synchronized 块解决线程冲突问题。
语法:
synchronized(syncObject) { //允许访问控制的代码 }
package com.test.java; /** * 测试没有线程同步机制异常 * @author 林 * */ public class TestThread { public static void main(String[] args) throws InterruptedException { Account a1=new Account("林",1000); Drawing d1=new Drawing(a1,800); Drawing d2=new Drawing(a1,700); d1.start(); d2.start(); } } class Account{ String name; int money; public Account(String name,int money) { super(); this.name=name; this.money=money; } } class Drawing extends Thread{ Account account; //账户 int drawingNum; //提取金额 int sum; //提取总金额 public Drawing(Account account,int drawingNum) { super(); this.account=account; this.drawingNum=drawingNum; } @Override public void run() { if((account.money-drawingNum)<0) { return; } try { Thread.sleep(2000); }catch(Exception e) { e.printStackTrace(); } account.money-=drawingNum; sum+=drawingNum; System.out.println(this.getName()+"账户余额:"+account.money); System.out.println(this.getName()+"提取总金额:"+sum); } }
输出结果:
Thread-0账户余额:-500
Thread-0提取总金额:800
Thread-1账户余额:-500
Thread-1提取总金额:700
package com.test.java; /** * 测试线程同步机制 * @author 林 * */ public class TestThread { public static void main(String[] args) throws InterruptedException { Account a1=new Account("林",1000); Drawing d1=new Drawing(a1,800); Drawing d2=new Drawing(a1,700); d1.start(); d2.start(); } } class Account{ String name; int money; public Account(String name,int money) { super(); this.name=name; this.money=money; } } class Drawing extends Thread{ Account account; //账户 int drawingNum; //提取金额 int sum; //提取总金额 public Drawing(Account account,int drawingNum) { super(); this.account=account; this.drawingNum=drawingNum; } @Override public void run() { draw(); } void draw() { synchronized(account) { //synchronized块,控制到具体的“成员变量” if((account.money-drawingNum)<0) { System.out.println(this.getName()+"余额不足"); return; } try { Thread.sleep(1000); //判断完后阻塞。其他线程开始运行 }catch(Exception e) { e.printStackTrace(); } account.money-=drawingNum; sum+=drawingNum; } System.out.println(this.getName()+"账户余额:"+account.money); System.out.println(this.getName()+"提取总金额:"+sum); } }
输出结果:
Thread-0账户余额:200
Thread-1余额不足
Thread-0提取总金额:800
死锁:多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能进行,而导致两个或者多个线程都在等待对方释放资源,都停止执行的情形。
解决方法:同一个代码块,不要同时持有两个对象锁。
package com.test.java; /** * 测试死锁 * @author 林 * */ public class TestThread { public static void main(String[] args) { C c1=new C(); c1.flag=0; C c2=new C(); c2.flag=1; c1.start(); c2.start(); } } class A{} class B{} class C extends Thread{ int flag; static A a=new A(); static B b=new B(); @Override public void run() { test(); } void test() { if(flag==0) { synchronized(a) { //获取a的锁 System.out.println("a1 running"); try { Thread.sleep(1000); }catch(Exception e) { e.printStackTrace(); } synchronized(b) { //获取b的锁 System.out.println("b1 running"); } } }else { synchronized(b) { //获取b的锁 System.out.println("b2 running"); try { Thread.sleep(1000); }catch(Exception e) { e.printStackTrace(); } synchronized(a) { //获取a的锁 System.out.println("a2 running"); } } } } }
输出结果:
a1 running
b2 running
package com.test.java; /** * 测试解决死锁 * @author 林 * */ public class TestThread { public static void main(String[] args) { C c1=new C(); c1.flag=0; C c2=new C(); c2.flag=1; c1.start(); c2.start(); } } class A{} class B{} class C extends Thread{ int flag; static A a=new A(); static B b=new B(); @Override public void run() { test(); } void test() { if(flag==0) { synchronized(a) { System.out.println("a1 running"); try { Thread.sleep(1000); }catch(Exception e) { e.printStackTrace(); } } synchronized(b) { System.out.println("b1 running"); } }else { synchronized(b) { System.out.println("b2 running"); try { Thread.sleep(1000); }catch(Exception e) { e.printStackTrace(); } } synchronized(a) { System.out.println("a2 running"); } } } }
输出结果:
b2 running
a1 running
a2 running
b1 running
多线程并发协作模型“生产者/消费者模式”。
java.lang.Object类的方法:
package com.test.java; /** * 测试生产/消费架构 * @author 林 * */ public class TestThread { public static void main(String[] args) { Buffer b1=new Buffer(); A a=new A(b1); B b=new B(b1); a.start(); b.start(); } } class Message{ //消息类 int id; Message(int id){ this.id=id; } } class Buffer{ //缓冲区类 int index=0; Message[] m1=new Message[10]; public synchronized void push(Message m) { while(index==m1.length) { //缓冲区类消息已满 try { this.wait(); //线程暂停,进入阻塞状态,等待消费 }catch(Exception e) { e.printStackTrace(); } } this.notify(); m1[index]=m; index++; } public synchronized Message pop() { while(index==0) { //缓冲区类消息已空 try { this.wait(); //线程暂停,进入阻塞状态,等待生产 }catch(Exception e) { e.printStackTrace(); } } this.notify(); index--; return m1[index]; } } class A extends Thread{ //生产类 Buffer b1=null; public A(Buffer b1) { this.b1=b1; } @Override public void run() { for(int i=0;i<10;i++) { System.out.println("生产:"+i); Message m1=new Message(i); b1.push(m1); } } } class B extends Thread{ //消费类 Buffer b1=null; public B(Buffer b1) { this.b1=b1; } @Override public void run() { for(int i=0;i<10;i++) { Message m1=b1.pop(); System.out.println("消费:"+i); } } }
java.util.Timer:定时或者每隔一定时间触发一次线程。
java.util.TimerTask:是一个抽象类,该类实现了Runnable接口,所以该类具备多线程的能力。
package com.test.java; import java.util.GregorianCalendar; import java.util.Timer; import java.util.TimerTask; /** * 测试任务调度 * @author 林 * */ public class TestThread { public static void main(String[] args) { Timer t1=new Timer(); MyTask m1=new MyTask(); t1.schedule(m1, 3000); //3秒后执行 //t1.schedule(m1,5000,1000); //5秒以后每隔1秒执行一次 //GregorianCalendar g1=new GregorianCalendar(2021,1,1,12,00,00); //指定时间 //t1.schedule(m1,g1.getTime()) } } class MyTask extends TimerTask{ public void run() { for(int i=0;i<10;i++) { System.out.println("任务:"+i); } } }
原文:https://www.cnblogs.com/linwenhai/p/14603832.html