1.单例设计模式
public class Demo1_Singleton {
/*
单例设计模式:保证类在内存中只有一个对象
*/
public static void main(String[] args) {
// Singleton s=Singleton.s; 成员变量被私有,不能通过类名.调用
Singleton s1=Singleton.getIntance();
Singleton s2=Singleton.getIntance();
System.out.println(s1==s2);
}
}
///*
// 方式一:饿汉式(开发时用)
// */
class Singleton{
//1.私有构造方法
private Singleton(){}
//2.创建实例对象
private static Singleton s=new Singleton();
//3.对外公开可调用的方法
public static Singleton getIntance(){
return s;
}
}
/*
方式二:懒汉式,(单例的延迟加载模式)(面试时用)
*/
class Singleton{
//1.私有构造方法
private Singleton(){}
//2.创建实例对象
private static Singleton s;
//3.对外公开可调用的方法
public static Singleton getIntance(){
if (s==null){
//线程1等待,线程2等待(可能创建多个对象)
s=new Singleton();
}
return s;
}
}
饿汉式和懒汉式的区别:
1.饿汉式是空间换时间。懒汉式是时间换空间
2.在多线程访问时,饿汉式不会创建多个对象,而懒汉式可能创建多个对象。
Runtime类
用了单例设计模式
Runtime r=Runtime.getRuntime();
r.exec("shutdown -s -t 300");//执行cmd命令
r.exec("shutdown -a");
2.Timer定时器类
timer定时器类,就是用线程实现的。以下代码为timer定时器类使用方法。
public class Demo3_TimerTask {
public static void main(String[] args) {
//Timer创建对象
Timer timer=new Timer();
//开启定时器,延时1000毫秒开始,每2000毫秒调用一次MyTimerTask()对象。
timer.schedule(new MyTimerTask(),1000,2000);
}
}
class MyTimerTask extends TimerTask{
@Override
public void run() {
//获取当前时间
Date data=new Date(System.currentTimeMillis());
//将时间格式化
SimpleDateFormat format=new SimpleDateFormat("HH:mm:ss");
System.out.println(format.format(data));
}
}
3.线程之间的通信
1.什么时候需要通信
* 多个线程并发执行的时候,在默认情况下CPU是随机切换线程的。
* 若我们希望他们有规律的执行,就可以使用通信。
2.怎么通信
* 如果希望线程等待,就调用wait();
* 如果希望唤醒等待的线程,就调用notify();
* 这两个方法必须在同步代码中执行,并使用同步锁对象来调用。
三个以上线程之间的通讯
- notify()方法是随机唤醒一个线程
- notifyAll()方法是唤醒所有线程
- JDK5之前是无法唤醒指定线程的
- 如果多个线程之间进行通信,需要使用notifyAll()方法是唤醒所有线程,用while来反复进行判断条件。
public class Demo1_Notify {
public static void main(String[] args) {
Printer p=new Printer();
//线程一
new Thread(){
@Override
public void run() {
while(true){
try {
p.print1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
//线程二
new Thread(){
@Override
public void run() {
while(true){
try {
p.print2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread(){
@Override
public void run() {
while(true){
try {
p.print3();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
class Printer{
private int flag=1;
public void print1() throws InterruptedException {
synchronized (this){
while (flag!=1){ //while是循环判断,每次都会判断标记。
this.wait(); //当前线程等待
}
System.out.print("1");
System.out.print("2");
System.out.print("3");
System.out.print("4");
System.out.print("5");
System.out.print("6");
System.out.print("7");
System.out.print("8");
System.out.println();
flag=2;
//this.notify(); //随机唤醒单个等待线程。
this.notifyAll(); //唤醒所有线程
}
}
public void print2() throws InterruptedException {
synchronized (this){
while (flag!=2){
this.wait();
}
System.out.print("湖");
System.out.print("北");
System.out.println();
flag=3;
//this.notify();
this.notifyAll(); //唤醒所有线程
}
}
public void print3() throws InterruptedException {
synchronized (this){
while (flag!=3){
this.wait();
}
System.out.print("hhhh");
System.out.print("bbbb");
System.out.println();
flag=1;
//this.notify();
this.notifyAll(); //唤醒所有线程
}
}
}
4.JDK1.5特性互斥锁
1.同步
- 使用ReentrantLock类的lock()和unlock()方法进行同步
2.通信
- 使用ReentrantLock类的newCondition()方法可以获取Condition对象
- 需要等待的时候使用newCondition的await()方法,唤醒的时候使用signal()方法
- 不同的线程使用不同的condition,这样就能精准唤醒指定线程
public class Demo2_ReentrantLock {
public static void main(String[] args) {
Printer2 p=new Printer2();
new Thread(){
@Override
public void run() {
while(true){
try {
p.print1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread(){
@Override
public void run() {
while(true){
try {
p.print2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread(){
@Override
public void run() {
while(true){
try {
p.print3();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
//等待唤醒机制
class Printer2{
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){ //while是循环判断,每次都会判断标记。
c1.await();//线程休眠
}
System.out.print("1");
System.out.print("2");
System.out.print("3");
System.out.print("4");
System.out.print("5");
System.out.print("6");
System.out.print("7");
System.out.print("8");
System.out.println();
System.out.println();
flag=2;
//this.notify(); //随机唤醒单个等待线程。
c2.signal();//唤醒c2对象的线程
r.unlock();
}
public void print2() throws InterruptedException {
r.lock();
if (flag!=2){
c2.await();
}
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("hhhh");
System.out.print("bbbb");
System.out.println();
flag=1;
//this.notify();
c1.signal();
r.unlock();
}
}
5.静态代理
静态代理模式:
要求代理类和被代理类使用同一个接口,重写其中的方法,代理类重写的方法实际上调用的是被代理类重写的方法。
测试代码:
package Agency.StaticDemo;
public interface Animal {
//叫声
public void cry();
//吃
public void eat();
}
被代理类:Cat
package Agency.StaticDemo;
public class Cat implements Animal{
@Override
public void cry() {
System.out.println("喵喵");
}
@Override
public void eat() {
System.out.println("吃鱼");
}
}
代理类:CatAgency
package Agency.StaticDemo;
public class CatAgency implements Animal{
//Cat是被代理的类,CatAgency是代理Cat的类
Cat cat;
public CatAgency(Cat cat){
this.cat=cat;
}
@Override
public void cry() {
System.out.println("CatAgency代理开始");
cat.cry();
System.out.println("CatAgency代理结束");
}
@Override
public void eat() {
System.out.println("CatAgency代理开始");
cat.eat();
System.out.println("CatAgency代理结束");
}
public static void main(String[] args) {
Cat cat=new Cat();
CatAgency catAgency=new CatAgency(cat);
catAgency.cry();
catAgency.eat();
}
}
执行结果:
6.动态代理
静态代理每代理一个对象,就要创建一个代理对象,很浪费空间。动态代理就解决了这个问题。
动态代理:当需要通过代理类来调用其它对象的方法,程序运行的时候可以动态的创建目标类的代理对象。
测试代码:
接口类
package Agency.ActiveDemo;
public interface Animal {
//叫声
public void cry();
//吃
public void eat();
}
实现接口类
package Agency.ActiveDemo;
public class Cat implements Animal {
@Override
public void cry() {
System.out.println("喵喵");
}
@Override
public void eat() {
System.out.println("吃鱼");
}
}
实现InvocationHandler接口的动态代理类
package Agency.ActiveDemo;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyProxy implements InvocationHandler {
private Object object;
public MyProxy(Object object){
this.object=object;
}
//method是对象执行的方法
//方法参数args
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("==============代理类开始执行!!!!=============");
//returnVal是方法的返回值
Object returnVal = method.invoke(object, args);
System.out.println("==============代理类执行结束!!!!=============");
return returnVal;
}
}
Main方法执行类
package Agency.ActiveDemo;
import java.lang.reflect.Proxy;
public class RunMain {
public static void main(String[] args) {
Cat cat=new Cat();
//创建动态代理
//1.执行invoke方法,获取对象的方法
MyProxy myProxy=new MyProxy(cat);
//2.实质上是通过反射将 被代理类的加载器 和 接口 与 代理对象 关联起来
Animal animal= (Animal) Proxy.newProxyInstance(
cat.getClass().getClassLoader(),//被代理对象的类加载器
cat.getClass().getInterfaces(),//被代理对象的接口
myProxy);//实现InvocationHandler接口的方法
animal.cry();
animal.eat();
}
}
推广一哈
大家如果有云存储的需求可以上九牛云存储https://s.qiniu.com/immAni,免费领取10G的存储空间。