上边博客写到单例设计模式,回顾一下,单例设计模式是不允许别的类创建对象,只允许自己创建对象,别的类想访问只能通过类名.调用, 这次举一个例子,JAVA中有一个类Runtime,这个类便是应用了单例设计模式。
代码走起
Demo5_Runtime.java
package com.tao.thread;
import java.io.IOException;
/**
* 多线程(Runtime类)
* @author 天外飞星
*
*/
public class Demo5_Runtime {
/**
*
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
Runtime runtime=Runtime.getRuntime();
// runtime.exec("shutdown -s -t 300"); //设置5分钟后关机
runtime.exec("shutdown -a"); //设置取消上次的关机设置
}
}
下面讲一个定时器的例子,每隔3s喊我起床背单词
Demo6_Timer.java
package com.tao.thread;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
/**
* 定时器
* @author 天外飞星
*
*/
public class Demo6_Timer {
public static void main(String[] args) throws InterruptedException {
Timer t=new Timer();
//三个参数,t.schedule(TimerTask的子类对象(指明任务),触发时间,多久执行一次)
//注:118是2018-1900得到的,,必须减去1900
t.schedule(new MyTimerTask(), new Date(118, 10, 18, 20, 40,30), 3000);
while(true){
Thread.sleep(1000);
System.out.println(new Date());
}
}
}
class MyTimerTask extends TimerTask{
public void run(){
System.out.println("起床背英语单词儿...");
}
}
两个线程间的通信
要求打印机执行完1后,马上把执行权给2,2执行完后立马把执行权给1,交替执行
实现一:
Demo1_Notify.java
package com.tao.thread2;
/**
* 交替执行
* 多线程(两个线程间的通信)
* @author 天外飞星
*
*
*/
public class Demo1_Notify {
public static void main(String[] args) {
final Printer p = new Printer();
new Thread() {
public void run() {
while (true) {
try {
p.print1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread() {
public void run() {
while (true) {
try {
p.print2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
class Printer {
private int flag = 1;
public void print1() throws InterruptedException {
synchronized (this) { // 同步代码块,锁机制,锁对象可以是任意的
if(flag!=1){
this.wait(); //当前线程等待
}
System.out.print("清");
System.out.print("华");
System.out.print("大");
System.out.print("学");
System.out.println();
flag=2;
this.notify(); //随机唤醒单个等待的进程
}
}
public void print2() throws InterruptedException {
synchronized (this) { // synchronized (new Demo())不可行,因为不是同一对象了
if(flag!=2){
this.wait();
}
System.out.print("我");
System.out.print("爱");
System.out.print("你");
System.out.println();
flag=1;
this.notify();
}
}
}
三个或三个以上间的线程通信
三个线程交替执行
Demo2_NotifyAll.java
package com.tao.thread2;
/**
* 多线程(三个或三个以上间的线程通信)
* @author 天外飞星
*
*/
public class Demo2_NotifyAll {
public static void main(String[] args) {
final Printer2 p1 = new Printer2();
new Thread() {
public void run() {
while (true) {
try {
p1.print1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread() {
public void run() {
while (true) {
try {
p1.print2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread() {
public void run() {
while (true) {
try {
p1.print3();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
class Printer2 {
private int flag = 1;
public void print1() throws InterruptedException {
synchronized (this) { // 同步代码块,锁机制,锁对象可以是任意的
if(flag!=1){
this.wait(); //当前线程等待
}
System.out.print("清");
System.out.print("华");
System.out.print("大");
System.out.print("学");
System.out.println();
flag=2;
// this.notify(); //随机唤醒单个等待的进程
this.notifyAll(); //唤醒所有进程,防止死锁
}
}
public void print2() throws InterruptedException {
synchronized (this) { // synchronized (new Demo())不可行,因为不是同一对象了
if(flag!=2){
this.wait();
}
System.out.print("我");
System.out.print("爱");
System.out.print("你");
System.out.println();
flag=3;
// this.notify();
this.notifyAll();
}
}
public void print3() throws InterruptedException {
synchronized (this) { // synchronized (new Demo())不可行,因为不是同一对象了
if(flag!=3){
this.wait();
}
System.out.print("I");
System.out.print("LOVE");
System.out.print("YOU");
System.out.println();
flag=1;
// this.notify();
this.notifyAll();
}
}
}
注意:三个以上线程通信要使用this.notifyAll(); 唤醒所有进程,防止死锁
三个或三个以上间的线程通信
实现二:
Demo3_ReentrantLock.java
package com.tao.thread2;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* 多线程(三个或三个以上间的线程通信)
* 多线程(JDK1.5的新特性互斥锁)
* @author 天外飞星
*
*/
public class Demo3_ReentrantLock {
public static void main(String[] args) {
final Printer3 p1 = new Printer3();
new Thread() {
public void run() {
while (true) {
try {
p1.print1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread() {
public void run() {
while (true) {
try {
p1.print2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread() {
public void run() {
while (true) {
try {
p1.print3();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
class Printer3 {
private int flag = 1;
private ReentrantLock r=new ReentrantLock(); //互斥锁
private Condition c1=r.newCondition(); //信号量
private Condition c2=r.newCondition(); //信号量
private Condition c3=r.newCondition(); //信号量
public void print1() throws InterruptedException {
r.lock(); //上锁
if(flag!=1){
c1.await(); //当前线程等待
}
System.out.print("清");
System.out.print("华");
System.out.print("大");
System.out.print("学");
System.out.println();
flag=2;
// this.notify(); //随机唤醒单个等待的进程
c2.signal();
r.unlock(); //解锁
}
public void print2() throws InterruptedException {
r.lock(); //上锁
if(flag!=2){
c2.await();
}
System.out.print("我");
System.out.print("爱");
System.out.print("你");
System.out.println();
flag=3;
// this.notify();
c3.signal();
r.unlock(); //解锁
}
public void print3() throws InterruptedException {
r.lock(); //上锁
if(flag!=3){
c3.await();
}
System.out.print("I");
System.out.print("LOVE");
System.out.print("YOU");
System.out.println();
flag=1;
// this.notify();
c1.signal();
r.unlock(); //解锁
}
}
为了对线程的统一管理,引入了组的概念,比如要对许多线程做同类操作,把这些线程加入到一个组内,,然后让改组实行操作即可。
Demo4_ThreadGroup.java
package com.tao.thread2;
/**
* 把t1,t2添加到一个线程组里
* @author 天外飞星
*
*/
public class Demo4_ThreadGroup {
public static void main(String[] args) {
MyRunable mr=new MyRunable();
ThreadGroup tg=new ThreadGroup("我是一个新的线程组");
Thread t1=new Thread(tg, mr);//把mr(未设置名称)线程添加到tg组
Thread t2=new Thread(tg, mr, "李四");//把叫李四的线程添加到tg组
System.out.println(t1.getName());
System.out.println(t2.getName());
System.out.println(t1.getThreadGroup().getName());
System.out.println(t2.getThreadGroup().getName());
//组方便对线程的同类操作
}
}
class MyRunable implements Runnable{
public void run(){
for(int i=1;i<10;i++){
System.out.println(Thread.currentThread().getName()+"...."+i);
}
}
}