Runtime
运行时对象,是一个单例类(只有一个对象的类)
每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。通过 getRuntime 方法获取当前运行时对象。
// RunTime 应用程序运行时对象
// 单例类 只能通过公开的静态方法进行调用
// 可以将应用程序与运行环境相结合
Runtime runtime = Runtime.getRuntime();
runtime.exec("shutdown -s -t 3");//可以执行cmd简单执行命令
//runtime.exec("shutdown -a"); //取消关机
Timer
Timer一种工具(计时器、定时器),用于在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) {
// 计时器/定时器
// 用于在指定时间后创建线程执行指定任务,并可以设置重复执行时间
Timer t1 = new Timer();
// t.schedule(task, Date time);
// 指定date日期执行
t1.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("指定日期执行");
t1.cancel();
}
}, new Date());
// t.schedule(task, long delay);
// 延时指定毫秒执行
Timer t2 = new Timer();
t2.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("指定毫秒后执行");
t2.cancel();
}
}, 1000);
// t.schedule(task, Date firstTime, long period);
// 指定date日期执行,指定毫秒重复执行
Timer t3 = new Timer();
t3.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("指定日期2s重复执行");
}
}, new Date(), 2000);
// t.schedule(task, long delay, long period);
// 延时指定毫秒执行,指定毫秒重复执行
Timer t4 = new Timer();
t4.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("1s后执行3s重复执行");
}
}, 1000, 3000);
}
}
多线程通信
线程通信概念:
线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程之间的通信就成为整体的必用方式之一。当线程存在通信指挥,系统间的交互性会更强大,在提高CPU利用率的同时还会对线程任务在处理过程中进行有效的把控与监督。
为了支持多线程之间的协作,JDK提供了两个非常重要的接口线程等待wait()方法和通知notify()方法。这两个方法并不是在Thread类中的,而是输出Object类。这也意味着任何对象都可以调用这2个方法。
public class TicketThread {
public static void main(String[] args) {
MyR mr = new MyR();
Thread t1 = new Thread(mr);
Thread t2 = new Thread(mr);
t1.start();
t2.start();
}
}
class MyR implements Runnable {
int t = 5;
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
synchronized (this) {
this.notify();// 唤醒等待的线程 等待的线程继续等待当前线程释放锁资源
if (t > 0) {
System.out.println(Thread.currentThread().getName() + "卖出第" + t-- + "张票");
} else {
break;
}
try {
this.wait();// 使当前正在使用锁资源的线程进入等待状态 并释放锁资源
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
注意
1、wait() 和 notify()必须配合synchrozied关键字使用,无论是wait()还是notify()都需要首先获取目标对象的一个监听器(锁对象)。
2、wait()释放锁,而notify()不释放锁。
3、锁对象不要使用包装类与String类对象,不能作为唯一标识
4、wait方法需要获取锁 ,只能让当前获取锁对象执行的线程等待(只能将自己进入等待状态)
5、notify方法不会释放锁,执行唤醒其他线程需要锁,就可以唤醒使用锁的线程
线程的生命周期
start()方法与run()方法的区别
1、状态转换区别
start方法是将线程由初始态转换为就绪态,run方法是将线程由就绪态转换为运行态。
2、调用者不同
start方法有我们调用启动线程,run方法有系统调用执行线程
3、赋予权限不同
start方法会赋予线程执行权,run方法是由系统赋予线程运行权(运行资源)后自动调用
4、执行次数不同
start方法在线程生命周期中只能执行一次,但是run方法可以执行很多次
run方法可不可以直接调用?
run方法本质就是一个方法。重写后创建指定对象通过对象.方法可以直接调用,但是,如果直接调用run方法与普通方法执行一样,会在主线程中直接执行,没有创建线程执行。
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("执行的线程" + Thread.currentThread().getName());
}
});
t.start();//执行的线程Thread-0
//t.run();//执行的线程main
}
voliate关键字
使变量在线程间可见
对于避免不可见性问题,Java还提供了一种弱形式的同步,即使用了volatile关键字。该关键字确保了对一个变量的更新对其他线程可见。当一个变量被声明为volatile时候,线程写入时候不会把值缓存在寄存器或者或者在其他地方,当线程读取的时候会从主内存重新获取最新值,而不是使用当前线程的拷贝内存变量值。volatile虽然提供了可见性保证,但是不能使用他来构建复合的原子性操作,也就是说当一个变量依赖其他变量或者更新变量值时候新值依赖当前老值时候不在适用。
JVM会尽力保证内存的可见性,即便这个变量没有加同步关键字。换句话说,只要CPU有时间,JVM会尽力去保证变量值的更新。这种与volatile关键字的不同在于,volatile关键字会强制的保证线程的可见性。而不加这个关键字,JVM也会尽力去保证可见性,但是如果CPU一直有其他的事情在处理,它也没办法。
public static void main(String[] args) {
Runnable r = new Runnable() {
volatile int t = 10;
@Override
public void run() {
while (t > 0) {
System.out.println(Thread.currentThread().getName() + "卖票" + t--);
}
}
};
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.start();
t2.start();
}
voliate关键字虽然强制保证可见性,但是由于系统cpu等限制,可能无法完全保证可见性,所以一般进行多线程编写时会与同步一同使用
设计模式
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
由大量开发人员经过不断的总结与完善用于解决一些固定功能或需求的代码
单例设计模式
一个类只允许拥有一个实例(这些类拥有限制,不能通过new创建对象 但是可以获取唯一对象,获取的对象无论怎么获取在当前程序中都是唯一对象)
简单点说,就是一个应用程序中,某个类的实例对象只有一个,你没有办法去new,因为构造器是被private修饰的,一般通过getInstance()的方法来获取它们的实例。getInstance()的返回值是一个对象的引用,并不是一个新的实例,所以不要错误的理解成多个对象。
最基本写法
//单例模式
public class SingletonTest {
// 一个类只允许存在一个实例对象
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1 == s2);
}
}
class Singleton {
// 单例类的书写
// 1书写唯一构造方法
// 2将构造方法私有
// 3提供公开静态方法获取对象
// 4在方法中创建唯一对象 声明变量属性
// 5如果没有唯一对象则创建 存在则返回
private static Singleton s = null;
private Singleton() {
}
public static Singleton getInstance() {
if (s == null) {
s = new Singleton();
}
return s;
}
}
懒汉模式(线程安全)
指的是创建对象的时间,在调用方法时才创建对象(不调用方法获取对象则不创建对象)
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
饿汉模式
在类声明时直接创建,调用方法则直接返回创建好的对象
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
工厂设计模式
将类的创建交由同一的工厂类进行处理,当我们需要使用某一个类时,可以通过工厂的静态方法直接输入获取类的类信息,功能相应方法会根据相应信息创建相应对象并返回
// 抽象产品类
interface class Car {
public void run();
public void stop();
}
// 具体实现类
class Benz implements Car {
public void run() {
System.out.println("Benz开始启动了。。。。。");
}
public void stop() {
System.out.println("Benz停车了。。。。。");
}
}
class Ford implements Car {
public void run() {
System.out.println("Ford开始启动了。。。");
}
public void stop() {
System.out.println("Ford停车了。。。。");
}
}
// 工厂类
class Factory {
public static Car getCarInstance(String type) {
Car c = null;
if ("Benz".equals(type)) {
c = new Benz();
}
if ("Ford".equals(type)) {
c = new Ford();
}
return c;
}
}
public class Test {
public static void main(String[] args) {
Car c = Factory.getCarInstance("Benz");
if (c != null) {
c.run();
c.stop();
} else {
System.out.println("造不了这种汽车。。。");
}
}
}
观察者设计模式
分为两种角色:观察者、被观察者
被观察者保存所有观察者信息,当被观察者发送消息所有观察者会收到相应信息
import java.util.ArrayList;
import java.util.List;
public class LookXiaoMei {
public static void main(String[] args) {
XiaoMei xiao_mei = new XiaoMei();
LaoWang lao_wang = new LaoWang();
LaoZhou lao_zhou=new LaoZhou();
LaoLi lao_li = new LaoLi();
// 老王和老李在小美那里都注册了一下
xiao_mei.addPerson(lao_wang);
xiao_mei.addPerson(lao_li);
xiao_mei.addPerson(lao_zhou);
// 小美向老王和老李发送通知
xiao_mei.notifyPerson();
}
}
interface Person {
// 老王和老李通过这个接口可以接收到小美发过来的消息
void getMessage(String s);
}
class LaoWang implements Person {
private String name = "老王";
public LaoWang() {
}
@Override
public void getMessage(String s) {
System.out.println(name + "接到了小美打过来的电话,电话内容是:" + s);
}
}
class LaoLi implements Person {
private String name = "老李";
public LaoLi() {
}
@Override
public void getMessage(String s) {
System.out.println(name + "接到了小美打过来的电话,电话内容是:" + s);
}
}
class LaoZhou implements Person {
private String name = "老周";
public LaoZhou() {
}
@Override
public void getMessage(String s) {
System.out.println(name + "接到了小美打过来的电话,电话内容是:" + s);
}
}
class XiaoMei {
List<Person> list = new ArrayList<Person>();
public XiaoMei() {
}
public void addPerson(Person person) {
list.add(person);
}
// 遍历list,把自己的通知发送给所有牌友
public void notifyPerson() {
for (Person person : list) {
person.getMessage("今天家里就我一个人,你们过来吧,谁先过来谁当地主!");
}
}
}
代理设计模式
https://blog.youkuaiyun.com/qq_38186465/article/details/80433858
先自己理解(我也只是个新手)