一、龟兔赛跑案例
/**
* 龟兔赛跑
* 跑道---作为资源类
*/
public class Race implements Runnable{
//当类一加载的时候,定义静态变量
//胜利者
private static String winner = null ;
//兔子和乌龟都要执行这个run
@Override
public void run() {
//for循环:表示步数1-100步
for(int x = 1 ; x <= 100 ; x ++){
//真实故事中:兔子要睡觉的,模拟兔子睡觉
if(Thread.currentThread().getName().equals("兔子") && (x % 10 ==0 )){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//定义一个定义比赛结束的方法
boolean flag = gameOver(x) ;
if(flag){
break ;
}
System.out.println(Thread.currentThread().getName()+"跑了====>"+x+"步");
}
}
//比赛结束的方法
private boolean gameOver(int step) {//步数 x
//情况1:如果当前winner不等于null,存在胜利者,比赛结束
if(winner!=null){
return true ;
}{
//情况2: 判断如果当前step>=100 比赛也要结束
if(step>=100){
winner = Thread.currentThread().getName() ;
System.out.println("winner is:"+winner);
return true ;
}
}
return false ;
}
//用户线程
public static void main(String[] args) {
//创建一个资源共享类
Race race = new Race() ;
//创建线程类对象
Thread t1 = new Thread(race,"兔子") ;
Thread t2 = new Thread(race,"乌龟") ;
t1.start();
t2.start();
}
}
举例:
public class Student {
private String name ;
private int age ;
private boolean flag ;
//定义一个功能:给学生赋值(产生数据)
public synchronized void set(String name,int age){ //同步方法 锁对象:this
//如果生产者有数据,等待消费者使用数据
if(this.flag){
try {
this.wait(); //立即释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name ;
this.age = age ;
//如果存在数据
this.flag = true ;
//唤醒阻塞中的线程:消费者线程
this.notify();
}
//获取学生的方法
public synchronized void get(){
//判断如果当前没有数据了,等待生产者生产数据
if(!this.flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(this.name+"---"+this.age);
//判断如果当前没有数据类,唤醒生产者线程,产生数据
this.flag = false ;
this.notify();
}
}
public class SetThread implements Runnable {
private Student s ;
public SetThread(Student s){
this.s = s ;
}
int x = 0 ;
@Override
public void run() {
//模拟生产者不断产生数据
while(true){
if(x % 2 ==0){
/*s.name = "高圆圆" ;
s.age = 41 ;*/
s.set("高圆圆",41);
}else{
/* s.name ="赵又廷";
s.age = 45 ;*/
s.set("耿明刚",26);
}
x ++;
}
}
}
public class GetThread implements Runnable {
private Student s ;
public GetThread(Student s ){
this.s = s ;
}
@Override
public void run() {
//模拟消费者不断使用数据
while(true){
s.get();
}
}
}
/**
* Java中等待唤醒机制
* SetThread:生产者资源类
* GetThrread:消费者资源类
* Student:学生
*/
public class ThreadDemo {
public static void main(String[] args) {
//创建学生对象
Student s = new Student() ;
//生产者资源类/消费者资源类对象
SetThread st = new SetThread(s) ;
GetThread gt = new GetThread(s) ;
//创建线程了对象
Thread t1 = new Thread(st) ;
Thread t2 = new Thread(gt) ;
t1.start();
t2.start();
}
}
二、线程组
线程组 ThreadGroup 线程组表示一个线程的集合
Thread类中方法:
public final ThreadGroup getThreadGroup():获取当前所有线程的默认线程组
ThreadGroup
public final String getName() :获取默认的线程组名称: (默认就是main)
构造方法:
ThreadGroup(String name):构造一个新的名称的线程组
所有的线程默认的线程组就是main线程(用户线程)
举例:
public class MyThread extends Thread {
@Override
public void run() {
for(int x = 0 ; x < 100 ; x ++){
System.out.println(getName()+":"+x);
}
}
}
public class ThreadGroupDemo {
public static void main(String[] args) {
//method() ;
method2() ;
}
//设置线程组名称
private static void method2() {
// ThreadGroup(String name):构造一个新的名称的线程组
ThreadGroup tg = new ThreadGroup("myMain") ;
//创建线程类对象:可以将线程组对象作为参数传递
//public Thread(ThreadGroup group,String name)
Thread t1 = new Thread(tg,"线程1") ;
Thread t2 = new Thread(tg,"线程2") ;
System.out.println(t1.getThreadGroup().getName());
System.out.println(t2.getThreadGroup().getName());
}
private static void method() {
//创建两个线程类对象
MyThread my1 = new MyThread() ;
MyThread my2 = new MyThread() ;
//获取对应的线程组名称
ThreadGroup tg1 = my1.getThreadGroup();
String name = tg1.getName();
ThreadGroup tg2 = my2.getThreadGroup();
String name2 = tg2.getName();
System.out.println(name);
System.out.println(name2);
}
}
三、线程池
-
线程池的使用:
1)接口:ExecutorService :跟踪一个或者多个异步任务
2)如何实例化---->Executors.newFixedThreadPool(int) 工厂方法: -
Executors:工厂类
提供创建线程池对象的方法
public static ExecutorService newFixedThreadPool(int nThreads) -
ExecutorService
方法:
Future<?> submit(Runnable task) :通过线程池提交异步任务
Future submit(Callable task):提交异步任务
Future:异步任务计算的结果!
第三种方式:线程池实现---->还是自定义一个类 实现Runnable接口
举例:
public class MyRunnable implements Runnable{
@Override
public void run() {
for(int x = 0 ; x < 100 ; x ++){
System.out.println(Thread.currentThread().getName()+":"+x);
}
}
}
/* MyCallabe:等待需要被线程池提交的异步任务
*/
public class MyCallable implements Callable<Object> {
//call方法:本身要计算的结果
@Override
public Object call() throws Exception {
for(int x = 0 ; x <100 ; x ++ ){
System.out.println(Thread.currentThread().getName()+":"+x);
}
return null;
}
}
public class ThreadDemo {
public static void main(String[] args) {
/* new Thread(){
@Override
public void run() {
}
}.start();*/
//创建一个线程池:静态工厂模式
ExecutorService pool = Executors.newFixedThreadPool(2);
//提交异步任务
// Future<?> submit(Runnable task) :通过线程池提交异步任务
/* pool.submit(new MyRunnable()) ;
pool.submit(new MyRunnable()) ;*/
//Callable要比Runnable接口更好
//可以跟踪具体的异常错误(如果执行过程中,线程出现异常,可以跟踪异常信息!)
pool.submit(new MyCallable()) ;
pool.submit(new MyCallable()) ;
//使用完毕,关闭线程池--将底层产生的线程归还线程池中
pool.shutdown();
}
}
举例:
/* 两条线程分别线程的求和
*/
public class MyCallable implements Callable<Integer> {
private int number ;
public MyCallable(int number){
this.number = number ;
}
//call方法:异步结果结果:它的返回值需要和Callable泛型的数据类型一致
//最终结果变量:
int sum = 0 ;
@Override
public Integer call() throws Exception { //就是线程执行的耗时操作 类似于 Runnable的run方法
for(int x = 1 ; x <= number; x ++){
sum+=x ;
}
return sum;
}
}
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ThreadDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建存有2条线程的线程池
ExecutorService executorService = Executors.newFixedThreadPool(2);
//Future:接口:异步计算的结果
Future<Integer> f1 = executorService.submit(new MyCallable(100));
Future<Integer> f2 = executorService.submit(new MyCallable(200));
//V get():获取结果值
Integer i1 = f1.get();
Integer i2 = f2.get();
System.out.println(i1);
System.out.println(i2);
}
}
四、定时器
java.util.Timer:定时器 :有线程安排执行务执行一次,或者定期重复执行。
构造方法:
public Timer() 无参构造方法
成员方法
public void cancel():取消定时器
public void schedule(TimerTask task,Date time) :在指定日期时间内执行这个任务
public void schedule(TimerTask task,long delay):在指定的延迟时间后执行task任务(时间:毫秒)
public void schedule(TimerTask task,
long delay,
long period) :在指定的delay延迟时间后开始重复时间间隔period来执行task任务
需求:
在某天的18点将 d://demo文件夹 中的所有的带后缀为.java文件删除掉! (Timer+io流+递归:综合使用)
public class TimerDemo {
public static void main(String[] args) {
//创建一个定时器
Timer timer = new Timer() ;
// public void cancel():取消定时器
//参数1:定时任务:抽象类,定义子类继承自TimerTask
// timer.schedule(new MyTask(timer),3000); :3秒后执行一次这个任务
/* public void schedule(TimerTask task,
long delay,
long period) :在指定的delay延迟时间后开始重复时间间隔period来执行task任务*/
timer.schedule(new MyTask(timer),2000,3000);
}
}
//定时任务
class MyTask extends TimerTask{ //TimerTask实现Runnable接口 ---会使用同步机制
private Timer t ;
public MyTask(Timer t){
this.t = t ;
}
@Override
public void run() {
System.out.println("bom...");
//关闭定时器
//t.cancel() ;
}
}
五、设计模式
- Java设计原则:
单一职责
接口分离
开闭原则
依赖注入原则(依赖于抽象类或者接口,而不依赖具体类实现)
举例:
public class Animal {
public void eat(){
System.out.println("动物都需要吃");
}
public void sleep(){
System.out.println("动物都需要休息");
}
}
public class Cat extends Animal {
public void eat(){
System.out.println("i can eat and eat mouse");
}
public void sleep(){
System.out.println("i can sleep ...");
}
}
public class Dog extends Animal{
public void eat(){
System.out.println("i can eat and eat meat");
}
public void sleep() {
System.out.println("i can sleep");
}
}
public class Pig extends Animal {
@Override
public void eat() {
System.out.println("eat");
}
@Override
public void sleep() {
System.out.println("sleep");
}
}
public class AnimalFactory {
//构造方法私有化
private AnimalFactory(){ //外界不能创建当前类对象
}
//静态方法
//创建猫的实例
/* public static Cat createCat(){
return new Cat() ;
}
//创建狗的实例
public static Dog createDog(){
return new Dog() ;
}
//创建猪的实例
public static Pig createPig(){
return new Pig() ;
}*/
//优化:利用多态:提供功能扩展
public static Animal createAnimal(String type){
if(type.equals("dog")){
return new Dog() ;
}else if(type.equals("cat")){
return new Cat() ;
}else if(type.equals("pig")){
return new Pig() ;
}else{
System.out.println("对不起,工厂类没有提供者动物的实例创建!");
}
return null ;
}
}
/* 创建型设计模式:对象的创建
* Java提供:简单工厂模式 ---静态工厂方法模式
* 优点:不需要具体类创建具体实例,通过工厂类创建
*
* 弊端:一旦有一个新的类型增,修改工厂类!
*
* 需要提供一个工厂类,负责具体的实例的创建
*/
public class Test {
public static void main(String[] args) {
//创建猫
Cat cat = new Cat() ;
cat.eat();
cat.sleep();
//狗
Dog dog = new Dog() ;
dog.eat();
dog.sleep();
System.out.println("------------------------");
//提供工厂类创建具体的动物实例
/* Cat c1 = AnimalFactory.createCat();
c1.eat();
c1.sleep();
Dog d = AnimalFactory.createDog() ;
d.eat();
d.sleep();*/
//优化之后
Animal animal = AnimalFactory.createAnimal("dog"); //父类引用指向子类对象
animal.eat();
animal.sleep();
animal = AnimalFactory.createAnimal("cat") ;
animal.eat();
animal.sleep();
}
}
举例:
public abstract class Animal {
public abstract 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 abstract Animal createAnimal() ;
}
public class CatFactory implements Factory{
@Override
public Animal createAnimal() {
return new Cat() ;
}
}
public class DogFactoy implements Factory {
@Override
public Animal createAnimal() {
return new Dog();
}
}
/* 工厂方法模式:
* 对象创建的工作:有一个接口完成
* 接口的子实现类---->创建具体实例的工厂类
* 优点:面向接口编程: 结构非常清晰,维护起来容易
* 弊端:代码量增加了,需要编写额外的工厂类...
*/
public class Test {
public static void main(String[] args) {
//没有使用工厂方法模式
//抽象类多态
Animal a = new Cat();
a.eat();
a = new Dog() ;
a.eat();
System.out.println("-----------------------------------");
//猫的工厂类
Factory f = new CatFactory() ;
Animal animal = f.createAnimal(); //new Cat()
animal.eat();
f = new DogFactoy() ;
Animal an = f.createAnimal();
an.eat();
}
}
public class Student {
//创建该类实例---(类的实例变量)
// public static Student s = new Student() ;
private static Student s = new Student() ;
private Student(){} //外界不能创建对象
//提供对外的公共访问方法:静态的
public static Student getStudent(){
return s ;
}
}
/* 创建型设计模式之单例
*
* 单例:
* 在加载某个类的时候,内存中始终只有一个对象!(该类对象自动创建)
*
* 两种:
* 饿汉式:特点 永远不会出现问题的单例模式!
* 在加载这个类的时候,就已经在内存中创建了一个对象!
* 1)自定义一个类(具体类)
* 2)成员位置:创建当前类的实例
* 3)提供私有的构造方法:外界不能够创建它
* 4)对外提供公共的访问方法:静态的,返回值当前类本身
*
* 懒汉式:可能出现问题的单例模式
* 1)自定义一个类(具体类)
* 2)成员位置:声明类型的变量
* 3)构造方法私有化
* 4)提供对外的公共访问方法:
* 需要判断:当前如果没有对象,new 对象
*
* 存在懒加载或者延迟加载!
* 可能出现多线程 安全问题:
*
* 如何解决
* 加同步锁
*
*
*/
public class Tests {
public static void main(String[] args) {
/*Student s =new Student() ;
Student s2 = new Student() ;
System.out.println(s==s2) ;//false
System.out.println(s.getClass()==s2.getClass());//true*/
//getClass()---->class 包名.类名
// Student.s = null ; //被外界更改掉
Student s1 = Student.getStudent();
Student s2 = Student.getStudent();
System.out.println(s1==s2);
System.out.println("-----------------");
Programmer p1 = Programmer.getPro();
Programmer p2 = Programmer.getPro();
Programmer p3 = Programmer.getPro();
System.out.println(p1==p2);
System.out.println(p1==p3);
}
}
public class Programmer {
private static Programmer pro = null ;
private Programmer(){}
//p1,p2,p3
//对外公共访问方法
/*public static Programmer getPro(){
synchronized (Programmer.class){
if(pro ==null){
pro = new Programmer() ;
}
return pro ;
}
}*/
public synchronized static Programmer getPro(){//静态同步方法:锁对象:当前类名.class属性
if(pro ==null){
pro = new Programmer() ;
}
return pro ;
}
}
举例:
/* 标准单例模式之饿汉式:Runtime
* 个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接
*/
public class RuntTimeDemo {
public static void main(String[] args) throws IOException {
Runtime runtime = Runtime.getRuntime();
// Runtime runtime2 = Runtime.getRuntime();
//System.out.println(runtime==runtime2);
int cpuSize = runtime.availableProcessors();
System.out.println(cpuSize);
runtime.exec("notepad") ;
runtime.exec("mspaint") ;
runtime.exec("calc") ;
}
}