Java基础笔记总结(17)-线程 单例模式 线程池 工厂模式 适配器模式 GUI

线程:

线程是程序的执行路径,一个进程包含多条线程

多线程的并发执行可以提高程序的效率,可以同时完成多项工作。

多行程并行和并发的区别

并行的使用 要使用多核CPU

并发指两个任务都运行,而处理器只能接受一个任务,将两个任务轮流执行

Java命令启动java虚拟机,启动JVM等于启动一个进程,该进程会自动启动一个“主线程”,然后主线程去调用某类的main方法

JVM的启动至少启动了垃圾回收线程和主线程,因此JVM是多线程的,注意线程是穿插执行

多线程

1、继承Thread,并且重写Thread的run方法,并分配和启动该子类的实例

public static void main(String[] args) {

MyThread mt = new MyThread();

mt.start();

for (int i = 0; i < 1000; i++) {

System.out.println("xxxxxxx");

}

}

}

class MyThread extends Thread{

@Override

public void run() {

for (int i = 0; i < 1000; i++) {

System.out.println("测试"+i);

}

}

2、实现Runnable()接口

new Thread(new Runnable() {

@Override

public void run() {

// TODO Auto-generated method stub

}

}).start();

-------------------------------------------------------------------------

Runnable和Thread的区别

a 继承Thread 由于子类重写了Thread类的run(),调用start()时,直接调用子类的run方法 实现代码简单,但是如果有父类,不能实现Thread。

b 实现Runnable 构造函数中传入Runnable的引用,成员变量通过记住它,start()调用run(方法)判断是否引用为空,如果不为空,编译Runnable的run(),运行时执行子类的run()方法,实现代码复杂,需要先获取到线程对象,才能使用Thread的方法

-------------------------------------------------------------------------

采用匿名内部类实现两种方法

new Thread(

public void run(){

}

).start();

new Thread(new Runnable(){

public void run(){

  }

}).start();

--------------------------------------------------------------------

获取

getName() 获取线程名称

new Thread(new Runnable() {

@Override

public void run() {

  this.getName();

}

}).start();

setName()可以改变名称或者在构造方法中修改名称

--------------------------------------------------------------------

获取当前线程的对象

Thread t = Thread.CurrentThread();

要使用Runnable接口,可以使用Thread.CurrentThread()获取当前线程;

-------------------------------------------------------------------

线程休眠

Thread.sleep(毫秒,纳秒);

-------------------------------------------------------------------

setDemon 守护线程

设置一个线程为守护线程,该线程不会单独执行,当其他非守护线程都执行结束后,自动退出

当非守护线程都执行结束后,自动退出

--------------------------------------------------------------------

加入线程

join()当前线程暂停,等待指定的线程执行结束后,当加入线程结束后,在继续执行线程

匿名内部类使用局部变量时候,必须用final修饰

使用局部变量

---------------------------------------------------------------------

礼让线程 yield()

---------------------------------------------------------------------

设置线程优先级

norm = 5

min = 1

max = 10

new Thread().setPriority(Thread.MIN_PRIORITY);

---------------------------------------------------------------------

同步代码块

当多段代码同时执行的过程中,我们希望cpu不要切换到其他线程工作,就需要同步操作

synchronized 同步代码块

锁对象是任意的,但是不能使用匿名内部类,因为匿名对象不是同一个对象

public static void main(String[] args) {

new Thread(){

public void run() {

Test t = new Test();

t.print1();

};

}.start();

new Thread(){

public void run() {

Test t = new Test();

t.print2();

};

}.start();

}

}

class Test {

static Lock lock = new Lock();

public static void print1(){

synchronized(lock){

System.out.println("xxxxxxx");

}

}

public static void print2(){

synchronized(lock){

System.out.println("yyyyyyyyy");

}

}

}

class  Lock{

public Lock(){

}

}

--------------------------------------------------------------------------

如果同步方法,在方法上加synchronized关键字即可

非静态的同步方法的锁对象是this

静态方法的同步方法锁对象是 Object.class 该类的字节码文件

------------------------------------------------------------------------

线程安全问题

铁路售票问题  共有100张,通过4个窗口买完

如果引用数据类型成员变量当成锁对象,要加静态类型

public class Demo_Ticket {

public static void main(String[] args) {

new Ticket().start();

new Ticket().start();

new Ticket().start();

new Ticket().start();

}

}

class Ticket extends Thread {

private static int ticket = 100;

@Override

public void run() {

while (true) {

synchronized (Ticket.class) {

if (ticket <= 0) {

break;

}

try {

Thread.sleep(10);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println(getName() + "....第" + ticket-- + "张");

}

}

}

}

---------------------------------------------------------------------------

Runnable接口实现

---------------------------------------------------------------------------

哲学家筷子问题 (不要出现同步代码块嵌套)

public class Demo_Lock {

private static String s1 = "筷子左";

private static String s2 = "筷子右";

public static void main(String[] args) {

new Thread (new Runnable() {

public void run() {

while (true) {

synchronized(s1){

System.out.println(Thread.currentThread().getName()+"获取"+s1+"等待"+s2);

synchronized(s2){

System.out.println("拿到"+s2+"开吃");

}

}

}

}

}).start();

new Thread (new Runnable() {

public void run() {

while (true) {

synchronized(s1){

System.out.println(Thread.currentThread().getName()+"获取"+s1+"等待"+s2);

synchronized(s2){

System.out.println("拿到"+s2+"开吃");

}

}

}

}

}).start();

new Thread (new Runnable() {

public void run() {

while (true) {

synchronized(s1){

System.out.println(Thread.currentThread().getName()+"获取"+s1+"等待"+s2);

synchronized(s2){

System.out.println("拿到"+s2+"开吃");

}

}

}

}

}).start();

new Thread (new Runnable() {

public void run() {

while (true) {

synchronized(s1){

System.out.println(Thread.currentThread().getName()+"获取"+s1+"等待"+s2);

synchronized(s2){

System.out.println("拿到"+s2+"开吃");

}

}

}

}

}).start();

}

}

Vector是线程安全的

ArrayList 是线程不安全的

StringBuffer 是线程安全的

StringBuilder 是线程不安全的

HashTable是线程安全的 HashMap是线程不安全的

将不安全的线程变成安全的 用类Collections

单例设计模式

public class Demo_SIngleton {

// 保证内存中只有一个对象

public static void main(String[] args) {

// Singleton s1 = new Singleton();

/*Singleton s1 = Singleton.s;

Singleton s2 =Singleton.s;

System.out.println(s1==s2);*/

Singleton s1 = Singleton.getInstance();

Singleton s2 = Singleton.getInstance();

System.out.println(s1==s2);

}

}

// 饿汉式 直接创建对象比较好  空间换时间 不会创建多个对象

class Singleton{

// 私有构造,其他类不能访问该构造方法

private Singleton(){}

// 创建本类对象 成员变量私有,不能调用

private static Singleton s = new Singleton();

// 对外提供公共的访问方法

public static Singleton getInstance(){

return s;

}

}

//懒汉式  会出现多线程的问题 时间换空间 有可能创建多个对象

class Singleton2{

// 私有构造,其他类不能访问该构造方法

private Singleton2(){}

// 创建本类对象 成员变量私有,不能调用

private static Singleton2 s ;

// 对外提供公共的访问方法

public static Singleton2 getInstance(){

if (s == null){

s = new Singleton2();

}

return s;

}

}

//

class Singleton3{

// 私有构造,其他类不能访问该构造方法

private Singleton3(){}

// 创建本类对象 成员变量私有,不能调用

private static final Singleton3 s = new Singleton3();;

// 对外提供公共的访问方法

public static Singleton3 getInstance(){

return s;

}

}

-----------------------------------------------------------------------------------

Runtime类

import java.io.IOException;

public class Demo_Runtime {

public static void main(String[] args) throws IOException {

//获取运行时对象

Runtime runTime = Runtime.getRuntime();

//执行字符串命令

//runTime.exec("shutdown -s -t 300");

runTime.exec("shutdown -a");

}

}

-------------------------------------------------------------------------------------

Timer 类(参数1:安排的任务 参数2:执行的时间 参数3:过多久再执行一次)

线程安排在后台执行任务,或者定期重复执行,指定时间安排指定任务

public class Demo_Timer {

public static void main(String[] args) throws InterruptedException {

Timer t = new Timer();

t.schedule(new MyTimerTask(),new Date(108,0,31,10,48,0), 5000);

while(true){

Thread.sleep(1000);

System.out.println(new Date());

}

}

}

class MyTimerTask extends TimerTask{

@Override

public void run() {

System.out.println("起床");

}

}

--------------------------------------------------------------------------------------

两个线程的通信(交替执行)

public class Demo_ThreadCommuicate {

//等待唤醒机制 wait() 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) {

// TODO Auto-generated catch block

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("A");

System.out.print("B");

System.out.print("\r\n");

flag = 2;

this.notify();

}

}

public  void print2() throws InterruptedException {

synchronized(this){

if(flag!=2){

this.wait();

}

System.out.print("Z");

System.out.print("W");

System.out.print("\r\n");

flag = 1;

this.notify();

}

}

}

-------------------------------------------------------------------------------

三个或三个以上线程的通信 notify()是随即唤醒线程

public class Demo_notifyAll {

public static void main(String[] args) {

final Printer2 printer2 = new Printer2();

new Thread(){

public void run() {

while(true){

try {

printer2.print1();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

};}.start();

new Thread(){

public void run() {

while(true){

try {

printer2.print2();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

};}.start();

new Thread(){

public void run() {

while(true){

try {

printer2.print3();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

};}.start();

}

}

class Printer2{

private int flag = 1;

public void print1() throws InterruptedException{

synchronized(this){

while(flag!=1){

this.wait();

}

System.out.print("A");

System.out.print("B");

System.out.print("\r\n");

flag = 2;

this.notifyAll();

}

}

public void print2() throws InterruptedException{

synchronized(this){

while (flag!=2){

this.wait();

}

System.out.print("M");

System.out.print("N");

System.out.print("\r\n");

flag = 3;

this.notifyAll();

}

}

public void print3() throws InterruptedException{

synchronized(this){

while(flag!=3){

this.wait();

}

System.out.print("Z");

System.out.print("W");

System.out.print("\r\n");

flag = 1;

this.notifyAll();

}

}

} }

}

注意事项:

在同步中,用什么对象作锁,就用什么对象wait()和notify()

wait方法和notify定义在Object,因为锁对象可以是任意对象,而Object是所有对象的基类

Sleep和wait的区别

sleep必须传入参数,参数就是时间,时间到,自动唤醒

wait方法,可以传入参数,也可以不传入参数,传入参数就是在参数的时间结束后等待,不传入参数就是直接等待

Sleep方法在同步函数或者同步代码块中,不释放锁

wait方法在同步代码块或者同步函数中,释放锁

------------------------------------------------------------------------------

JDK1.5 互斥锁

ReentrantLock类的lock() unlock()替换synchronized

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.ReentrantLock;

public class Demo_Lock {

public static void main(String[] args) {

final Printer3 p3 = new Printer3();

new Thread(){

public void run() {

while(true){

try {

p3.print1();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

};}.start();

new Thread(){

public void run() {

while(true){

try {

p3.print2();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

};}.start();

new Thread(){

public void run() {

while(true){

try {

p3.print3();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

};}.start();

}

}

class Printer3 {

private ReentrantLock r = new ReentrantLock();

private int flag = 1;

private Condition c1 = r.newCondition();

private Condition c2 = r.newCondition();

private Condition c3 = r.newCondition();

public void print1() throws InterruptedException {

r.lock();

while (flag != 1) {

c1.await();

}

System.out.print("A");

System.out.print("B");

System.out.print("\r\n");

flag = 2;

c2.signal();

r.unlock();

}

public void print2() throws InterruptedException {

r.lock();

while (flag != 2) {

c2.await();

}

System.out.print("M");

System.out.print("N");

System.out.print("\r\n");

flag = 3;

c3.signal();

r.unlock();

}

public void print3() throws InterruptedException {

r.lock();

while (flag != 3) {

c3.await();

}

System.out.print("Z");

System.out.print("W");

System.out.print("\r\n");

flag = 1;

c1.signal();

r.unlock();

}

}

lock()上锁

unlock()解锁

Condition c = r.newCondition();

c.await() == this.wait()

c.singnal() == this.notifyAll()  可以指定线程而无需全部唤醒

----------------------------------------------------------------

线程组的概述和使用

TreadGroup 表示线程组,允许对一群线程组管理 Java允许其对线程组管理

public class Demo_ThreadGroup {

public static void main(String[] args) {

MyRunnable myRunnable = new MyRunnable();

Thread t1 = new Thread(myRunnable,"张三");

Thread t2 = new Thread(myRunnable,"李四");

ThreadGroup tg1 = t1.getThreadGroup();//默认是主线程

System.out.println(tg1.getName());

ThreadGroup tg2 = t2.getThreadGroup();//默认是主线程

System.out.println(tg2.getName());

//如何设置线程组

ThreadGroup tg = new ThreadGroup("我是新的线程组");

MyRunnable mr = new MyRunnable();

Thread t3 = new Thread(tg,mr,"张三");

Thread t4 = new Thread(tg,mr,"李四");

Thread t5 = new Thread(tg,mr,"王五");

System.out.println(t3.getThreadGroup().getName());

tg.setDaemon(true);

}

}

class MyRunnable implements Runnable{

@Override

public void run() {

for (int i = 0; i < 1000; i++) {

System.out.println(Thread.currentThread().getName()+"..."+i);

}

}

}

------------------------------------------------------------------

线程的五种状态

线程的生命周期:

新建 创建线程对象

就绪 想成对象已经启动,但未获得CPU执行权

运行 获得CPU执行权

阻塞 没有CPU执行权,回到就绪

死亡 代码运行完毕,线程消亡

-------------------------------------------------------------------

线程池的概述和使用

使用线程池能够很好提高性能,尤其当程序中创建大量生命周期较短的线程时,更要考虑线程池,线程池中的代码结束后,并不会死亡,而是返回线程池变成空闲状态,

Java内置的线程池Executors工厂类来产生线程吃 有以下方法

public static ExecutorService newFixedThreadPool(int nThreads)

public static ExecutorService newSingleThreadExecutor()

这些方法返回的是ExecutorService对象,可以执行Runnable对象或者Callable对象代表的线程们提供了

Future submit(Runnable task)

Future task)

创建步骤:

创建线程池对象

创建Runnable实例

提交Runnbale实例

关闭线程池

// 创建线程池

ExecutorService pool = Executors.newFixedThreadPool(2);

pool.submit(new MyRunnable());//将县城放入池中并并行

pool.submit(new MyRunnable());

pool.shutdown();//关闭线程池

-----------------------------------------------------------------------------

多线程(多线程程序实现的方式)

提交的是Callable

import java.util.Iterator;

import java.util.concurrent.Callable;

import java.util.concurrent.ExecutionException;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Future;

public class Demo_Callable {

public static void main(String[] args) throws InterruptedException, ExecutionException {

ExecutorService pool = Executors.newFixedThreadPool(2);

Future f1 =  pool.submit(new MyCallable(100));

System.out.println(f1.get());

Future f2 =  pool.submit(new MyCallable(50));

System.out.println(f2.get());

pool.shutdown();

}

}

class MyCallable implements Callable{

private int num ;

public  MyCallable(int num) {

this.num = num;

}

@Override

public Integer call() throws Exception {

int sum = 0;

for (int i = 0; i <= num; i++) {

sum+=i;

}

return sum;

}

}

------------------------------------------------------------------------------------------------

简单工厂模式

称为 静态工厂方法模式,定义一个具体工厂类来创建类的实例

优点:客户端不需要在负责对象的创建,从而明确了各个类的职责

缺点:该静态工厂负责所有类的创建,如果有对象增加,或者修改对象创建方式,就要不断的修改工厂类,不利于维护啊

-------------------------------------------------------------------------------------------------

工厂方法模式 (抽象工厂类负责定义创建对象的接口,具体对象的创建工作由继承抽象工厂的具体类实现)

将工厂类抽取成接口,对不同的对象生成不同的工厂来生产产品

public interface Factory {

public Animal createAnimal();

}

public class DogFactory implements Factory {

@Override

public Animal createAnimal() {

return new Dog();

}

}

----------------------------------------------------------------------------------------------------

GUI界面显示

Graphical User Interface

Frame f = new Frame("xxxx");

f.setLayout();

f.setSize(400,600);

f.setLocation(300,50);

f.setIcomImage(Toolkit.getDefaultToolkit().createImage());

FlowLayout 流式布局管理器

BorderLayout 边界布局管理器

GridLayout 网格布局管理器

CardLayout 卡片布局管理器

GridBagLayout 网格背包管理器

f.setVisible(true);//设置窗体可见

GUI布局管理器

-----------------------------------------------------------------------------------------------------

窗体的监听

f.addWindowListener();  //windowAdapter 实现了WIndowListener,并且重写了空方法

鼠标监听

f.addMouseListener();  MouseAdapter重写部分方法

键盘监听

f.addKeyListener();      KeyAdapter()适配监听 Event.VK_Z

动作监听

button.addActionListener  执行actionPerFormed(ActionEvent e)//添加动作场景

--------------------------------------------------------------------------------------------------------

适配器设计模式

定义一个类事件的监听器接口

适配器简化了操作,定义监听器时候只要集成适配器,然后重写了需要的方法即可

适配器类必须是抽象的

适配器类重写方法,但是方法全部为空,但是实际上是你需要那个方法就重写哪个方法,起到了一个过渡的作用

你可能感兴趣的:(Java基础笔记总结(17)-线程 单例模式 线程池 工厂模式 适配器模式 GUI)