Java se:多线程和简单的设计模式

本文介绍了Java中的多线程概念、实现方式,包括继承Thread类、实现Runnable接口和Callable接口。详细讲解了线程调度、控制、生命周期、线程安全问题以及同步机制。此外,还探讨了线程池、定时器Timer和TimerTask的使用,并概述了单例、简单工厂和工厂方法等设计模式的应用。
摘要由CSDN通过智能技术生成

概念

  • 进程:正在执行的应用程序
  • 线程:进程的执行单元,执行路径
  • 单线程:一个应用程序只有一条执行路径
  • 多线程:一个应用程序有多条执行路径
  • 多进程的意义?
    提高CPU的使用率
    多线程的意义?
    提高应用程序的使用率
  • Java程序的运行原理及JVM的启动是多线程的
    A:Java命令去启动JVM,JVM会启动一个进程,该进程会启动一个主线程。
    B:JVM的启动是多线程的,因为它最低有两个线程启动了,主线程和垃圾回收线程。

实现方式1:继承Thread类

public class MyThread extends Thread {
	public MyThread() {
	}
	public MyThread(String name){
		super(name);
	}
	@Override
	public void run() {
		for (int x = 0; x < 200; x++) {
			System.out.println(getName() + ":" + x);
		}
	}
}
public class MyThreadDemo {
	public static void main(String[] args) {
		MyThread my1 = new MyThread();
		MyThread my2 = new MyThread();
		my1.start();
		my2.start();
	}
}
  • Thread类的基本获取和设置方法
    1.public final String getName()
    2.public final void setName(String name)
    3.通过构造方法
  • public static Thread currentThread() //获取任意方法所在的线程名称

线程调度

  • 抢占式调度模型:
    优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些。
  • 获取和设置线程优先级
    public final int getPriority()
    public final void setPriority(int newPriority)
    默认是5
    范围是1-10

线程控制

  • 线程休眠
    public static void sleep(long millis)
    线程加入
    public final void join()
    线程礼让
    public static void yield()
    后台线程
    public final void setDaemon(boolean on)
    中断线程
    public final void stop()
    public void interrupt()

线程的生命周期

在这里插入图片描述
在这里插入图片描述

实现方式2:实现Runnable接口

public class MyRunnable implements Runnable {
	@Override
	public void run() {
		for (int x = 0; x < 100; x++) {
			// 由于实现接口的方式就不能直接使用Thread类的方法了,但是可以间接的使用
			System.out.println(Thread.currentThread().getName() + ":" + x);
		}
	}
}
public class MyRunnableDemo {
	public static void main(String[] args) {
		// 创建MyRunnable类的对象
		MyRunnable my = new MyRunnable();
		Thread t1 = new Thread(my, "张三");
		Thread t2 = new Thread(my, "李四");
		t1.start();
		t2.start();
	}
}
  • 好处:
    可以避免由于Java单继承带来的局限性。
    适合多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码,数据有效分离,较好的体现了面向对象的设计思想。

实现方式3:Callable接口

扩展:实现Callable接口。这个得和线程池结合。

线程安全问题

  • 分析原因:
    A:是否有多线程环境
    B:是否有共享数据
    C:是否有多条语句操作共享数据
  • 解决线程安全问题:(同步)
    • 同步代码块 锁可以是任意对象
synchronized(对象) {
				需要被同步的代码;
			}
    • 同步方法
      把同步加在方法上。这里的锁对象是this
    • 静态同步方法
      把同步加在方法上。这里的锁对象是当前类的字节码文件对象
  • 为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock
    • // 定义锁对象
      private Lock lock = new ReentrantLock();
      ReentrantLock是Lock的实现类.
    • // 加锁
      lock.lock();
      // 释放锁
      lock.unlock();
  • 等待唤醒机制:
    • Object类中提供了三个方法:
      wait():等待
      notify():唤醒单个线程
      notifyAll():唤醒所有线程
  • 死锁问题:
    两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待现象
    同步代码块的嵌套案例

线程池/线程组

  • 默认情况下,所有的线程都属于主线程组。
    public final ThreadGroup getThreadGroup()
    我们也可以给线程设置分组
    Thread(ThreadGroup group, Runnable target, String name)
  • 启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。
  • 线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
  • JDK5新增了一个Executors工厂类来产生线程池
    public static ExecutorService newCachedThreadPool()

匿名内部类方式使用多线程

// 继承Thread类来实现多线程
		new Thread() {
			public void run() {
				for (int x = 0; x < 100; x++) {
					System.out.println(Thread.currentThread().getName() + ":"
							+ x);
				}
			}
		}.start();
// 实现Runnable接口来实现多线程
		new Thread(new Runnable() {
			@Override
			public void run() {
				for (int x = 0; x < 100; x++) {
					System.out.println(Thread.currentThread().getName() + ":"
							+ x);
				}
			}
		}) {
		}.start();

定时器Timer和TimerTask

定时器:可以让我们在指定的时间做某件事情,还可以重复的做某件事情。

多线程常见问题

  • run()和start()它们的区别?
    run():封装了被线程执行的代码,直接调用仅仅是普通方法的调用
    start():启动线程,并由JVM自动调用run()方法
  • sleep()和wait()方法的区别
    sleep():必须指时间;不释放锁。
    wait():可以不指定时间,也可以指定时间;释放锁。
  • 为什么wait(),notify(),notifyAll()等方法都定义在Object类中
    因为这些方法的调用是依赖于锁对象的,而同步代码块的锁对象是任意锁。
    而Object代码任意的对象,所以,定义在这里面。

简单的设计模式

单例模式

  • 保证类在内存中只有一个对象
  • 单例模式饿汉式:(类一加载就创建对象,不会出线程安全问题的单例模式)
public class Student {
	// 构造方法私有
	private Student() {
	}
	// 自己造一个
	// 静态方法只能访问静态成员变量,加静态
	private static Student s = new Student();

	// 提供公共的访问方式
	// 为了保证外界能够直接使用该方法,加静态
	public static Student getStudent() {
		return s;
	}
}
  • 单例模式懒汉式:(用的时候,才去创建对象,可能会出线程安全问题的单例模式)
public class Teacher {
	private Teacher() {
	}
	private static Teacher t = null;
	public synchronized static Teacher getTeacher() {
		if (t == null) {
			t = new Teacher();
		}
		return t;
	}
}
  • Runtime类
    • JDK提供的一个单例模式应用的类。可以调用dos命令
    • Runtime:每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。
    • 使用:Runtime r = Runtime.getRuntime(); r.exec(“calc”);

简单工厂模式

又叫静态工厂方法模式,它定义一个具体的工厂类负责创建一些类的实例

工厂方法模式

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值