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)

<T> Future<T submit(Callable<T> 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<Integer> f1 =  pool.submit(new MyCallable(100));

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

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

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 = 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)//添加动作场景

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

适配器设计模式

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

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

适配器类必须是抽象的

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 进程和线程 进程 所有运行中的任务通常对应一个进程,当一个程序进入内存运行时,即变成一个进程.进程是处于运行过程中...
    胜浩_ae28阅读 5,084评论 0 23
  • Java多线程学习 [-] 一扩展javalangThread类 二实现javalangRunnable接口 三T...
    影驰阅读 2,948评论 1 18
  • 本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 首先讲...
    李欣阳阅读 2,438评论 1 15
  • 现在很多人会有失眠,失眠的原因有很多,今天跟大家分享的有3种原因,第一种是心肾不交,第二种是脾胃不和,第三种是气血...
    凤娟_3533阅读 168评论 0 0
  • 一元钱的盘子, 被遗弃在阴泠的角落里冰凉刺骨。 昏暗无天日虚度残日。 立在远处的镜子看见了, 对它说怎么了? 盘子...
    淑女_2e7d阅读 356评论 2 1