Java多线程(下)
单例设计模式
保证类在内存中只有一个本类对象
饿汉式
public class Demo_Singleton {
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
}
}
class Singleton{
//私有构造方法
private Singleton(){}
//创建本类对象
private static Singleton s = new Singleton();
public static Singleton getInstance(){
return s;
}
}
懒汉式
public class Demo_Singleton {
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
}
}
class Singleton{
//私有构造方法
private Singleton(){}
//声明引用
private static Singleton s;
public static Singleton getInstance(){
if(s==null)
s=new Singleton();
return s;
}
}
这种方式,在多线程中可能会出现创建了多个对象。
第三种方式
public class Demo_Singleton {
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
}
}
class Singleton{
//私有构造方法
private Singleton(){}
//创建本类对象
public static final Singleton s = new Singleton();
}
Runtime类(单例设计模式应用)
import java.io.IOException;
public class Demo_Runtime {
public static void main(String[] args) throws IOException {
Runtime r = Runtime.getRuntime();
r.exec("shutdown - s -t 300");
}
}
Timer(计时器)
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class Demo_Timer {
public static void main(String[] args) {
Timer t = new Timer();
t.schedule(new MyTimerTask(),new Date(119,6,30,11,5,30));//在指定时间安排指定任务
/*
* 第一个参数是安排的任务,第二个参数是执行的时间,若有第三个参数则是过多长时间重复执行
* new Date(year,month,date,hrs,min,sec)
* year - 减1900的年份
* month - 0-11之间的月份
* date - 一月中1-31的某一天
* hrs - 0-23之间的小时
* min - 0-59的分钟
* sec - 0-59的秒
*/
}
}
class MyTimerTask extends TimerTask{
@Override
public void run() {
System.out.println("起床背单词!!");
}
}
线程间的通信注意的问题
-
在同步代码块中,用哪个对象锁,就用哪个对象调用wait()方法
-
为什么wait()和notify()方法定义在Object这类中?
因为锁对象可以是任意对象,Object是所有类的基类
-
sleep()和wait()方法的区别
-
sleep方法必须传入参数,参数就是时间,时间到了自动醒来
wait方法可以传入参数也可以不传入参数,传入参数就是在参数的时间过了之后等待,不传入参数就是立即等待
-
sleep方法在同步方法或同步代码块中不释放锁
wait方法在同步方法或同步代码块中释放锁
-
互斥锁
**使用ReentrantLock类的lock()和unlock()方法进行同步 **
使用Condition的await()和signal()方法来使线程等待或唤醒,与notify()方法不同的是signal()可以唤醒指定线程
public class Demo_Thread {
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();
new Thread(){
public void run(){
while(true){
try {
p.print3();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
class Printer {
private ReentrantLock r = new ReentrantLock();
private Condition c1 = r.newCondition();
private Condition c2 = r.newCondition();
private Condition c3 = r.newCondition();
private int flag = 1;
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;
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.print("程");
System.out.print("师");
System.out.println();
flag = 3;
c3.signal();
r.unlock();
}
public void print3() throws InterruptedException{
r.lock();
if(flag != 3){
c3.await();
}
System.out.print("后");
System.out.print("台");
System.out.print("程");
System.out.print("序");
System.out.print("员");
System.out.println();
flag = 1;
c1.signal();
r.unlock();
}
}
//输出:
前端工程师
后台程序员
安卓开发
前端工程师
后台程序员
安卓开发
前端工程师
后台程序员
安卓开发
前端工程师
后台程序员
线程组的概述和使用
概述
Java中使用ThreadGroup来表示线程组,它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制。
默认是主线程
public class Demo_ThreadGroup {
public static void main(String[] args) {
MyRunnable mr = new MyRunnable();
Thread t1 = new Thread(mr,"张三");
Thread t2 = new Thread(mr,"李四");
ThreadGroup tg1 = t1.getThreadGroup();
ThreadGroup tg2 = t2.getThreadGroup();
System.out.println(tg1.getName());
System.out.println(tg2.getName());
}
}
class MyRunnable implements Runnable{
public void run(){
for (int i = 0;i<1000;i++){
System.out.println(Thread.currentThread().getName()+"..."+i);
}
}
}
//输出:main
main
创建线程组
通过Thread的构造方法将线程添加进线程组
线程的五种状态
线程池
1.概述
程序启动一个新线程的成本是比较高的,因为它涉及到要与操作系统进行交互。而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存周期很短的线程时,更应该考虑线程池。线程池里面的每一个线程代码结束后并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
ExecutorsService pool = Executors.newFixedThreadPool(n);//n是线程池中的线程数量
pool.submit();//向线程池中添加线程并执行
pool.shutdown();//关闭线程池