单例设计模式(重要)
- 保证类在内存中只有一个对象
- 饿汉式, 空间换时间, 类创建的时候就创建对象, 线程安全的
- 懒汉式, 双叫单例加载模式, 使用的时候才创建对象, 存在线程安全问题
- 区别, 饿汉式空间换时间, 懒汉式时间换空间, 多线程访问时, 饿汉式不会创建多个对象, 懒汉式可能创建多个对象
public class Demo1_Singleton {
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1);
System.out.println(s2 == s1);
}
}
class Singleton{
// 1. 私有化构造函数, 就不能随意实例类了
private Singleton (){}
// 2. 创建实例
private static Singleton s = new Singleton();
// 3. 饿汉式
public static Singleton getInstance() {
return s;
}
}
class SingletonLazy{
private SingletonLazy (){}
private static SingletonLazy s ;
public static SingletonLazy getInstance() {
if(s == null){
s = new SingletonLazy();
}
return s;
}
}
class SingletonFinal{
private SingletonFinal(){}
public static final SingletonFinal s = new SingletonFinal();
}
Runtime 类
- Process exec(String command) throws IOException 执行命令
import java.io.IOException;
public class Demo2_Runtime {
public static void main(String[] args) throws IOException {
Runtime runtime = Runtime.getRuntime();
runtime.exec("ls");
}
}
Timer ( 可以被ScheduledExecutorService取代 )
- 一种工具, 线程用其安排以后在后台线程中执行的任务, 可安排任务执行一次, 或者定期重复执行
private static void demo1() {
Timer t = new Timer();
// t.schedule(new MyTimerTask(), new Date(121,8,13,11,8,01); // 定时 执行
// 循环执行, 每3秒执行一次
t.schedule(new MyTimerTask(), new Date(121,8,13,11,8,01),3000);
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(new Date());
}
}
ScheduledExecutorService
- Time的缺陷, 单线程多个任务排队, 一个任务执行时间长了, 后面任务受影响, 一个任务挂了, 后面的任务无法执行, 强依赖系统时间, 系统时间更改则会更改
- ScheduledExecutorService 多线程, 则没有上述问题
- ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) 延时initialDelay, 开始周期delay执行
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Demo3_Timer {
public static void main(String[] args) throws InterruptedException {
// 一个任务出现 异常, 不影响其他任务
ScheduledExecutorService ses = Executors.newScheduledThreadPool(2);
ses.scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
System.out.println("===" + Thread.currentThread().getName() + "===");
}
}
, 0, 3, TimeUnit.SECONDS);
ses.scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
int i = 1/0;
System.out.println("***" + Thread.currentThread().getName() + "***");
}
}
, 0, 3, TimeUnit.SECONDS);
}
private static void demo2(){
// 一个任务执行时间长了, 也不会任务其他任务
ScheduledExecutorService ses = Executors.newScheduledThreadPool(2);
ses.scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
System.out.println("===" + Thread.currentThread().getName() + "===");
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
, 0, 3, TimeUnit.SECONDS);
ses.scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
System.out.println("***" + Thread.currentThread().getName() + "***");
}
}
, 0, 3, TimeUnit.SECONDS);
}
private static void demo1() {
Timer t = new Timer();
// t.schedule(new MyTimerTask(), new Date(121,8,13,11,8,01); // 定时 执行
// 循环执行, 每3秒执行一次
t.schedule(new MyTimerTask(), new Date(121,8,13,11,8,01),3000);
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(new Date());
}
}
}
class MyTimerTask extends TimerTask{
@Override
public void run() {
System.out.println("起来上班");
}
}
多个线程的通信(重要)
- this.notify() 随机唤醒单个等待线程
public class Demo1_Notify {
public static void main(String[] args) {
Printer p = new Printer();
new Thread(){
@Override
public void run() {
while (true){
try {
p.method1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread(){
@Override
public void run() {
while (true){
try {
p.method2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
class Printer{
private int flag = 1;
public void method1() throws InterruptedException {
synchronized (this){
if(flag != 1){
this.wait();
}
System.out.println("aaaa");
flag = 2;
this.notify();
}
}
public void method2() throws InterruptedException {
synchronized (this){
if(flag != 2){
this.wait();
}
System.out.println("bbbbbbbb");
flag = 1;
this.notify();
}
}
}
三个或三个以上间的线程通信
public class Demo2_Notify3 {
public static void main(String[] args) {
Printer2 p = new Printer2();
new Thread(){
@Override
public void run() {
while (true){
try {
p.method1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread(){
@Override
public void run() {
while (true){
try {
p.method2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread(){
@Override
public void run() {
while (true){
try {
p.method3();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
class Printer2{
private int flag = 1;
public void method1() throws InterruptedException {
synchronized (this){
while (flag != 1){
this.wait();
}
System.out.println("aaaa");
flag = 2;
this.notifyAll();
}
}
public void method2() throws InterruptedException {
synchronized (this){
while (flag != 2){
this.wait();
}
System.out.println("bbbbbbbb");
flag = 3;
this.notifyAll();
}
}
public void method3() throws InterruptedException {
synchronized (this){
while (flag != 3){
this.wait();
}
System.out.println("cccccccccccccc");
flag = 1;
this.notifyAll();
}
}
}
线程间通信注意的问题
- 1.在同步代码块中,用哪个对象锁,就用哪个对象调用wait方法
- 2.为什么wait方法和notify方法定义在Object这类中?
- 因为锁对象可以是任意对象,Object是所有的类的基类,所以wait方法和notify方法需要定义在Object这个类中
- 3.sleep方法和wait方法的区别?
- a,sleep方法必须传入参数,参数就是时间,时间到了自动醒来
- wait方法可以传入参数也可以不传入参数,传入参数就是在参数的时间结束后等待,不传入参数就是直接等待
- b,sleep方法在同步函数或同步代码块中,不释放锁,睡着了也抱着锁睡
- wait方法在同步函数或者同步代码块中,释放锁
互斥锁(重要) ReentrantLock Condition
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Demo3_ReentrantLock {
public static void main(String[] args) {
Printer3 p = new Printer3();
new Thread(){
@Override
public void run() {
while (true) {
try {
p.method1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread(){
@Override
public void run() {
while (true) {
try {
p.method2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread(){
@Override
public void run() {
while (true) {
try {
p.method3();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
class Printer3{
private int flag = 1;
private ReentrantLock r = new ReentrantLock();
Condition c1 = r.newCondition();
Condition c2 = r.newCondition();
Condition c3 = r.newCondition();
public void method1() throws InterruptedException {
r.lock();
if (flag != 1){
c1.await();
}
System.out.println("aaaa");
flag = 2;
c2.signal();
r.unlock();
}
public void method2() throws InterruptedException {
r.lock();
if (flag != 2){
c2.await();
}
System.out.println("bbbbbbbb");
flag = 3;
c3.signal();
r.unlock();
}
public void method3() throws InterruptedException {
r.lock();
if(flag != 3){
c3.await();
}
System.out.println("cccccccccccccc");
flag = 1;
c1.signal();
r.unlock();
}
}
线程组
public class Demo4_ThreadGroup {
public static void main(String[] args) {
// demo1();
ThreadGroup threadGroup = new ThreadGroup("自造线程组");
Mythread mythread = new Mythread();
Runnable target;
Thread t1 = new Thread(threadGroup, mythread);
Thread t2 = new Thread(threadGroup,mythread,"线程1");
Thread t3 = new Thread(threadGroup,mythread,"线程2");
System.out.println(t1.getName());
System.out.println(t2.getName());
System.out.println(t3.getName());
System.out.println(t1.getThreadGroup().getName());
System.out.println(t2.getThreadGroup().getName());
System.out.println(t3.getThreadGroup().getName());
System.out.println(t1.getThreadGroup().getParent().getName());
}
private static void demo1() {
Mythread mythread = new Mythread();
Thread t1 = new Thread(mythread);
Thread t2 = new Thread(mythread);
ThreadGroup tg1 = t1.getThreadGroup();
ThreadGroup tg2 = t2.getThreadGroup();
System.out.println(tg1.getName());
System.out.println(tg2.getName());
}
}
class Mythread implements Runnable{
@Override
public void run() {
}
}
线程的5种状态
- 新建线程.start() -> 线程就绪状态, 有执行权->抢到CPU执行权限执行->死亡状态, run执行完了
- 抢到CPU执行权限执行->wait或sleep线程阻塞->叫醒线,程线程就绪状态, 有执行权
线程池
- 程序创建一个线程成本比较高, 为了方便使用线程池, 使用后再返给JVM
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo5_Executors {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(2);
pool.submit(new Mythread());
pool.submit(new Mythread());
pool.shutdown();
}
}
实现Callable的线程
import java.util.concurrent.*;
public class Demo6_Callable {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService pool = Executors.newFixedThreadPool(2);
Future<Integer> f1 = pool.submit(new MyCallable(10));
Future<Integer> f2 = pool.submit(new MyCallable(20));
System.out.println(f1.get());
System.out.println(f2.get());
pool.shutdown();
}
}
class MyCallable implements Callable<Integer>{
private int num;
public MyCallable(int num){
this.num = num;
}
@Override
public Integer call() throws Exception {
int sum = 0;
for(int i=1;i<num;i++){
sum = sum + i;
}
return sum;
}
}
简单工厂模式
- 概述 静态工厂方法模式, 它定义一个具体的工厂类负责创建一些类的实例
- 优点 客户端不负责对象的创建, 从而明确各类的职责
- 缺点 静态工厂负责所有类的创建, 如果有新的对象或者新对象创建方式不同, 就需要不断修改工厂类, 不利于后期维护.
public abstract class Animal {
public void eat(){};
}
public class AnimalFactory {
public static Dog createDog(){
return new Dog();
}
public static Cat createCat(){
return new Cat();
}
public static Animal createAnimal(String animal){
if( "dog".equals(animal)){
return new Dog();
} else if( "cat".equals(animal)){
return new Cat();
}
return null;
}
}
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("单身狗儿吃狗粮");
}
}
``
public class Test {
public static void main(String[] args) {
Dog dog = AnimalFactory.createDog();
System.out.println(dog);
Dog d = (Dog) AnimalFactory.createAnimal("dog");
d.eat();
Cat c = (Cat) AnimalFactory.createAnimal("cat");
c.eat();
}
}
工厂方法模式
- 工厂方法模式中看网易工厂类负责定义创建对象的接口, 具体对象的创建工作由继承工厂的具体类实现
- 做点
- 客户端不需要在负责对象的创建, 从而明确了各个类的职责, 如果有新的对象增加, 只需要增加一个具体的类和
- 俱体的工厂类即可, 不影响已有的代码, 后期维护容易, 增强了系统扩展性
- 缺点 需要额外编写代码, 增加工作量
public abstract class Animal {
public void eat(){};
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("单身狗儿吃狗粮");
}
}
public interface Factory {
public Animal createAnimal();
}
public class CatFactory implements Factory{
@Override
public Animal createAnimal() {
return new Cat();
}
}
public class DogFactory implements Factory{
@Override
public Animal createAnimal() {
return new Dog();
}
}
public class Test {
public static void main(String[] args) {
DogFactory dogFactory = new DogFactory();
Dog d = (Dog) dogFactory.createAnimal();
d.eat();
CatFactory catFactory = new CatFactory();
Cat c = (Cat) catFactory.createAnimal();
c.eat();
}
}
Gui 了解, 暂用不到
import java.awt.*;
public class Demo1_Frame {
public static void main(String[] args) {
Frame f = new Frame();
f.setTitle("我的窗口");
f.setLocation(500,400);
f.setSize(400,300);
f.setIconImage(Toolkit.getDefaultToolkit().createImage("favicon.png"));
f.setVisible(true);
}
}
布局和按钮
import java.awt.*;
public class Demo1_Frame {
public static void main(String[] args) {
Frame f = new Frame();
f.setTitle("我的窗口");
f.setLocation(500,400);
f.setSize(400,300);
f.setIconImage(Toolkit.getDefaultToolkit().createImage("favicon.png"));
f.setLayout(new FlowLayout());
Button button = new Button("按钮");
Button button2 = new Button("按钮");
f.add(button);
f.add(button2);
f.setVisible(true);
}
}
监听的3种方式
- 类实现WindowListener接口
- 类继承WindowAdapter
- 匿名内部类 new WindowAdapter()
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
public class Demo1_Frame {
public static void main(String[] args) {
Frame f = new Frame();
f.setTitle("我的窗口");
f.setLocation(500,400);
f.setSize(400,300);
f.setLayout(new FlowLayout());
Button button = new Button("按钮");
// MyWindow myWindow = new MyWindow();
// f.addWindowListener(myWindow);
// MyAdapter myAdapter = new MyAdapter();
// f.addWindowListener(myAdapter);
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.add(button);
f.setVisible(true);
}
}
class MyAdapter extends WindowAdapter{
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
class MyWindow implements WindowListener{
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
@Override
public void windowClosed(WindowEvent e) {
System.out.println("Colosed");
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
}
鼠标监听
- 同样有3种方式
- 实现MouseListener 接口
- 继承MouseAdapter抽象类
- 匿名内部类new MouseAdapter
import java.awt.*;
import java.awt.event.*;
public class Demo1_Frame {
public static void main(String[] args) {
Frame f = new Frame();
f.setTitle("我的窗口");
f.setLocation(500,400);
f.setSize(400,300);
f.setLayout(new FlowLayout());
Button button = new Button("按钮");
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.add(button);
button.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
System.exit(0);
}
});
f.setVisible(true);
}
}
键盘监听和键盘事件
- 实现KeyListener 接口
- 继承 KeyAdapter 抽象类
- 匿名内部类new KeyAdapter()
import java.awt.*;
import java.awt.event.*;
public class Demo1_Frame {
public static void main(String[] args) {
Frame f = new Frame();
f.setTitle("我的窗口");
f.setLocation(500,400);
f.setSize(400,300);
f.setLayout(new FlowLayout());
Button button = new Button("按钮");
// MyWindow myWindow = new MyWindow();
// f.addWindowListener(myWindow);
// MyAdapter myAdapter = new MyAdapter();
// f.addWindowListener(myAdapter);
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.add(button);
button.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
System.exit(0);
}
});
button.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_SPACE){
System.exit(0);
}
}
});
f.setVisible(true);
}
}
动作监听
- 实现ActionListener 接口
- 匿名内部类 new ActionListener()类
import java.awt.*;
import java.awt.event.*;
public class Demo1_Frame {
public static void main(String[] args) {
Frame f = new Frame();
f.setTitle("我的窗口");
f.setLocation(500,400);
f.setSize(400,300);
f.setLayout(new FlowLayout());
Button button = new Button("按钮");
Button button2 = new Button("按钮二");
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.add(button);
f.add(button2);
button.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
System.exit(0);
}
});
button.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_SPACE){
System.exit(0);
}
}
});
button2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
f.setVisible(true);
}
}
设计模式-适配器模式
- 什么是适配器
- 在使用监听器的时候, 需要定义一个事件监听器的接口
- 通常接口中有多个方法, 而程序中不一定所有的都用到, 但又必须重写, 这很繁琐
- 我在楼下器简化了这些操作, 我们定义监听器时只要继承我在楼下器, 然后重写需要的方法即可
- 适配器原理
- 适配器就是一个类, 实现了监听器接口, 所有抽象方法都重写了, 但是方法全是空的
- 我在楼下器类需要定义成抽象的, 因为创建类对象, 调用空方法是没有意义的
- 目的就是为了简化程序员的操作, 定义监听时继承适配器, 中重写需要的方法就可以了
GUI(需要知道的)
- 事件处理
- 事件: 用户的一个操作
- 事件源: 被操作的组件
- 监听器: 一个自定义类的对象, 实现了监听器接口, 包含事件处理方法, 监听器添加在事件源上, 当事件发生的时候虚拟机就会自动调用监听器中的事件处理方法