24(02)多线程锁,线程通讯,线程组,线程池,多线程三种方式,匿名内部类,定时器,设计模式,单例模式,Runtime

(6)多线程实现的第三种方案
package cn.itcast_09;(1)
import java.util.concurrent.Callable;
//Callable:是带泛型的接口。
//这里指定的泛型其实是call()方法的返回值类型。
public class MyCallable implements Callable {
 @Override
 public Object call() throws Exception {
 for (int x = 0; x < 100; x++) {
 System.out.println(Thread.currentThread().getName() + ":" + x);
 }
 return null;
 }
}
package cn.itcast_09;(2)
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/*
 * 多线程实现的方式3:
 *   A:创建一个线程池对象,控制要创建几个线程对象。
 *  public static ExecutorService newFixedThreadPool(int nThreads)
 *  B:这种线程池的线程可以执行:
 *  可以执行Runnable对象或者Callable对象代表的线程
 *  做一个类实现Runnable接口。
 *  C:调用如下方法即可
 *  Future<?> submit(Runnable task)
 * <T> Future<T> submit(Callable<T> task)
 * D:我就要结束,可以吗?
 * 可以。
 */
public class CallableDemo {
 public static void main(String[] args) {
 //创建线程池对象
 ExecutorService pool = Executors.newFixedThreadPool(2);
 //可以执行Runnable对象或者Callable对象代表的线程
 pool.submit(new MyCallable());
 pool.submit(new MyCallable());
 //结束
 pool.shutdown();
 }
}

(7)多线程的面试题

package cn.itcast_10;(1)
import java.util.concurrent.Callable;
/*
 * 线程求和案例
 */
public class MyCallable implements Callable<Integer> {
 private int number;
 public MyCallable(int number) {
 this.number = number;
 }
 @Override
 public Integer call() throws Exception {
 int sum = 0;
 for (int x = 1; x <= number; x++) {
 sum += x;
 }
 return sum;
 }
}
package cn.itcast_10;(2)
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/*
 * 多线程实现的方式3:
 *   A:创建一个线程池对象,控制要创建几个线程对象。
 *  public static ExecutorService newFixedThreadPool(int nThreads)
 *  B:这种线程池的线程可以执行:
 *  可以执行Runnable对象或者Callable对象代表的线程
 *  做一个类实现Runnable接口。
 *  C:调用如下方法即可
 *  Future<?> submit(Runnable task)
 * <T> Future<T> submit(Callable<T> task)
 * D:我就要结束,可以吗?
 * 可以。
 */
public class CallableDemo {
 public static void main(String[] args) throws InterruptedException, ExecutionException {
 // 创建线程池对象
 ExecutorService pool = Executors.newFixedThreadPool(2);
 // 可以执行Runnable对象或者Callable对象代表的线程
 Future<Integer> f1 = pool.submit(new MyCallable(100));
 Future<Integer> f2 = pool.submit(new MyCallable(200));
 // V get()
 Integer i1 = f1.get();
 Integer i2 = f2.get();
 System.out.println(i1);
 System.out.println(i2);
 // 结束
 pool.shutdown();
 }
}

(8)匿名内部类的方式实现多线程

package cn.itcast_11;
/*
 * 匿名内部类的格式:
 *  new 类名或者接口名() {
 *  重写方法;
 *  };
 *  本质:是该类或者接口的子类对象。
 */
public class ThreadDemo {
 public static void main(String[] args) {
 // 继承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();
 // 更有难度的
 new Thread(new Runnable() {
 @Override
 public void run() {
 for (int x = 0; x < 100; x++) {
 System.out.println("hello" + ":" + x);
 }
 }
 }) {
 public void run() {
 for (int x = 0; x < 100; x++) {
 System.out.println("world" + ":" + x);
 }
 }
 }.start();
 }
}

(9)定时器概述和使用

package cn.itcast_12;
import java.util.Timer;
import java.util.TimerTask;
/*
 * 定时器:可以让我们在指定的时间做某件事情,还可以重复的做某件事情。
 * 依赖Timer和TimerTask这两个类:
 * Timer:定时
 *  public Timer()
 *  public void schedule(TimerTask task,long delay)
 *  public void schedule(TimerTask task,long delay,long period)
 *  public void cancel()
 * TimerTask:任务
 */
public class TimerDemo {
 public static void main(String[] args) {
 // 创建定时器对象
 Timer t = new Timer();
 // 3秒后执行爆炸任务
 // t.schedule(new MyTask(), 3000);
 //结束任务
 t.schedule(new MyTask(t), 3000);
 }
}
// 做一个任务
class MyTask extends TimerTask {
 private Timer t;
 public MyTask(){}
 public MyTask(Timer t){
 this.t = t;
 }
 @Override
 public void run() {
 System.out.println("beng,爆炸了");
 t.cancel();
 }
}

(10)定时器任务多次执行代码体现

package cn.itcast_12;
import java.util.Timer;
import java.util.TimerTask;
/*
 * 定时器:可以让我们在指定的时间做某件事情,还可以重复的做某件事情。
 * 依赖Timer和TimerTask这两个类:
 * Timer:定时
 *  public Timer()
 *  public void schedule(TimerTask task,long delay)
 *  public void schedule(TimerTask task,long delay,long period)
 *  public void cancel()
 * TimerTask:任务
 */
public class TimerDemo2 {
 public static void main(String[] args) {
 // 创建定时器对象
 Timer t = new Timer();
 // 3秒后执行爆炸任务第一次,如果不成功,每隔2秒再继续炸
 t.schedule(new MyTask2(), 3000, 2000);
 }
}
// 做一个任务
class MyTask2 extends TimerTask {
 @Override
 public void run() {
 System.out.println("beng,爆炸了");
 }
}

(11)定时器删除指定带内容目录

package cn.itcast_12;
import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
/*
 * 需求:在指定的时间删除我们的指定目录(你可以指定c盘,但是我不建议,我使用项目路径下的demo)
 */
class DeleteFolder extends TimerTask {
 @Override
 public void run() {
 File srcFolder = new File("demo");
 deleteFolder(srcFolder);
 }
 // 递归删除目录
 public void deleteFolder(File srcFolder) {
 File[] fileArray = srcFolder.listFiles();
 if (fileArray != null) {
 for (File file : fileArray) {
 if (file.isDirectory()) {
 deleteFolder(file);
 } else {
 System.out.println(file.getName() + ":" + file.delete());
 }
 }
 System.out.println(srcFolder.getName() + ":" + srcFolder.delete());
 }
 }
}
public class TimerTest {
 public static void main(String[] args) throws ParseException {
 Timer t = new Timer();
 String s = "2014-11-27 15:45:00";
 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 Date d = sdf.parse(s);
 t.schedule(new DeleteFolder(), d);
 }
}

(12)扩展:多线程常见的面试题

A.多线程有几种实现方案,分别是哪几种?

两种。

继承Thread类

实现Runnable接口

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

B.同步有几种方式,分别是什么?

两种。

同步代码块

同步方法

C.启动一个线程是run()还是start()?它们的区别?

start();

run():封装了被线程执行的代码,直接调用仅仅是普通方法的调用

start():启动线程,并由JVM自动调用run()方法

D.sleep()和wait()方法的区别

sleep():必须指时间;不释放锁。

wait():可以不指定时间,也可以指定时间;释放锁。

E.为什么wait(),notify(),notifyAll()等方法都定义在Object类中

因为这些方法的调用是依赖于锁对象的,而同步代码块的锁对象是任意锁。

而Object代码任意的对象,所以,定义在这里面。

F.线程的生命周期图

新建 -- 就绪 -- 运行 -- 死亡

新建 -- 就绪 -- 运行 -- 阻塞 -- 就绪 -- 运行 -- 死亡

建议:画图解释。

2:设计模式(理解)

(1)面试对象的常见设计原则

单一

其实就是开发人员经常说的”高内聚,低耦合”

也就是说,每个类应该只有一个职责,对外只能提供一种功能,

而引起类变化的原因应该只有一个。在设计模式中,所有的设计模式都遵循这一原则。

开闭

核心思想是:一个对象对扩展开放,对修改关闭。

其实开闭原则的意思就是:对类的改动是通过增加代码进行的,而不是修改现有代码。

也就是说软件开发人员一旦写出了可以运行的代码,就不应该去改动它,而是要保证它能一直运行下去,

如何能够做到这一点呢?这就需要借助于抽象和多态,即把可能变化的内容抽象出来,从而使抽象的部分是相对稳定的,

而具体的实现则是可以改变和扩展的。

里氏

核心思想:在任何父类出现的地方都可以用它的子类来替代。

其实就是说:同一个继承体系中的对象应该有共同的行为特征。

依赖注入

核心思想:要依赖于抽象,不要依赖于具体实现。

其实就是说:在应用程序中,所有的类如果使用或依赖于其他的类,则应该依赖这些其他类的抽象类,而不是这些其他类的具体类。

为了实现这一原则,就要求我们在编程的时候针对抽象类或者接口编程,而不是针对具体实现编程。

接口分离原则

核心思想:不应该强迫程序依赖它们不需要使用的方法。

其实就是说:一个接口不需要提供太多的行为,一个接口应该只提供一种对外的功能,不应该把所有的操作都封装到一个接口中。

迪米特

核心思想:一个对象应当对其他对象尽可能少的了解

其实就是说:降低各个对象之间的耦合,提高系统的可维护性。在模块之间应该只通过接口编程,而不理会模块的内部工作原理,

它可以使各个模块耦合度降到最低,促进软件的复用

(2)设计模式概述和分类

 A:经验的总结

 B:三类

    创建型  创建对象

    结构型  对象的组成

    行为型  对象的功能

(3)改进的设计模式

 A:简单工厂模式

简单工厂模式概述:

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

优点:

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

缺点:

这个静态工厂类负责所有对象的创建,如果有新的对象增加,或者某些对象的创建方式不同,就需要不断的修改工厂类,不利于后期的维护

package cn.itcast_01;(1)
public abstract class Animal {
 public abstract void eat();
}
package cn.itcast_01;(2)
public class Dog extends Animal {
 @Override
 public void eat() {
 System.out.println("狗吃肉");
 }
}
package cn.itcast_01;(3)
public class Cat extends Animal {
 @Override
 public void eat() {
 System.out.println("猫吃鱼");
 }
}
package cn.itcast_01;(4)
public class AnimalDemo {
 public static void main(String[] args) {
 // 具体类调用
 Dog d = new Dog();
 d.eat();
 Cat c = new Cat();
 c.eat();
 System.out.println("------------");
 // 工厂有了后,通过工厂给造
 // Dog dd = AnimalFactory.createDog();
 // Cat cc = AnimalFactory.createCat();
 // dd.eat();
 // cc.eat();
 // System.out.println("------------");
 // 工厂改进后
 Animal a = AnimalFactory.createAnimal("dog");
 a.eat();
 a = AnimalFactory.createAnimal("cat");
 a.eat();
 // NullPointerException
 a = AnimalFactory.createAnimal("pig");
 if (a != null) {
 a.eat();
 } else {
 System.out.println("对不起,暂时不提供这种动物");
 }
 }
}
package cn.itcast_01;(5)
public class AnimalFactory {
 private AnimalFactory() {
 }
 // public static Dog createDog() {
 // return new Dog();
 // }
 //
 // public static Cat createCat() {
 // return new Cat();
 // }
 public static Animal createAnimal(String type) {
 if ("dog".equals(type)) {
 return new Dog();
 } else if ("cat".equals(type)) {
 return new Cat();
 } else {
 return null;
 }
 }
}

 B:工厂方法模式

简单工厂模式概述:

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

优点:

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

缺点:

这个静态工厂类负责所有对象的创建,如果有新的对象增加,或者某些对象的创建方式不同,就需要不断的修改工厂类,不利于后期的维护

package cn.itcast_02;(1)
public abstract class Animal {
 public abstract void eat();
}
package cn.itcast_02;(2)
public interface Factory {
 public abstract Animal createAnimal();
}
package cn.itcast_02;(3)
public class AnimalDemo {
 public static void main(String[] args) {
 // 需求:我要买只狗
 Factory f = new DogFactory();
 Animal a = f.createAnimal();
 a.eat();
 System.out.println("-------");
 //需求:我要买只猫
 f = new CatFactory();
 a = f.createAnimal();
 a.eat();
 }
}
package cn.itcast_02;(4)
public class Dog extends Animal {
 @Override
 public void eat() {
 System.out.println("狗吃肉");
 }
}
package cn.itcast_02;(5)
public class DogFactory implements Factory {
 @Override
 public Animal createAnimal() {
 return new Dog();
 }
}
package cn.itcast_02;(6)
public class Cat extends Animal {
 @Override
 public void eat() {
 System.out.println("猫吃鱼");
 }
}
package cn.itcast_02;(7)
public class CatFactory implements Factory {
 @Override
 public Animal createAnimal() {
 return new Cat();
 }
}

 C:单例模式(掌握)

a:饿汉式

package cn.itcast_03;(1)
public class Student {
 // 构造私有
 private Student() {
 }
 // 自己造一个
 // 静态方法只能访问静态成员变量,加静态
 // 为了不让外界直接访问修改这个值,加private
 private static Student s = new Student();
 // 提供公共的访问方式
 // 为了保证外界能够直接使用该方法,加静态
 public static Student getStudent() {
 return s;
 }
}
package cn.itcast_03;(2)
/*
 * 单例模式:保证类在内存中只有一个对象。
 * 
 * 如何保证类在内存中只有一个对象呢?
 *  A:把构造方法私有
 *  B:在成员位置自己创建一个对象
 *  C:通过一个公共的方法提供访问
 */
public class StudentDemo {
 public static void main(String[] args) {
 // Student s1 = new Student();
 // Student s2 = new Student();
 // System.out.println(s1 == s2); // false
 // 通过单例如何得到对象呢?
 // Student.s = null;
 Student s1 = Student.getStudent();
 Student s2 = Student.getStudent();
 System.out.println(s1 == s2);
 System.out.println(s1); // null,cn.itcast_03.Student@175078b
 System.out.println(s2);// null,cn.itcast_03.Student@175078b
 }
}

b:懒汉式

package cn.itcast_03;(1)
/*
 * 单例模式:
 *  饿汉式:类一加载就创建对象
 *  懒汉式:用的时候,才去创建对象
 * 
 * 面试题:单例模式的思想是什么?请写一个代码体现。
 * 
 *  开发:饿汉式(是不会出问题的单例模式)
 *  面试:懒汉式(可能会出问题的单例模式)
 *  A:懒加载(延迟加载) 
 *  B:线程安全问题
 *  a:是否多线程环境 是
 *  b:是否有共享数据 是
 *  c:是否有多条语句操作共享数据  是
 */
public class Teacher {
 private Teacher() {
 }
 private static Teacher t = null;
 public synchronized static Teacher getTeacher() {
 // t1,t2,t3
 if (t == null) {
 //t1,t2,t3
 t = new Teacher();
 }
 return t;
 }
}
package cn.itcast_03;(2)
public class TeacherDemo {
 public static void main(String[] args) {
 Teacher t1 = Teacher.getTeacher();
 Teacher t2 = Teacher.getTeacher();
 System.out.println(t1 == t2);
 System.out.println(t1); // cn.itcast_03.Teacher@175078b
 System.out.println(t2);// cn.itcast_03.Teacher@175078b
 }
}

(4)Runtime

JDK提供的一个单例模式应用的类。

还可以调用dos命令。

package cn.itcast_03;
import java.io.IOException;
/*
 * Runtime:每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。
 * exec(String command)
 */
public class RuntimeDemo {
 public static void main(String[] args) throws IOException {
 Runtime r = Runtime.getRuntime();
// r.exec("winmine");
 // r.exec("notepad");
 // r.exec("calc");
// r.exec("shutdown -s -t 10000");
 r.exec("shutdown -a");
 }
}
/*
 * class Runtime {
 *  private Runtime() {}
 *  private static Runtime currentRuntime = new Runtime();
 *  public static Runtime getRuntime() {
 *        return currentRuntime;
 *    }
 * }
 */

原文发布于微信公众号 - Java帮帮(javahelp)

原文发表时间:2016-12-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏求索之路

android阿里面试java基础锦集

接着上一篇 android阿里面试锦集 今天给大家带来一篇 android阿里面试java基础锦集。很多知识都是Thinking in Java上面的,所以如...

383110
来自专栏逆向技术

逆向知识第七讲,三目运算符在汇编中的表现形式,以及编译器优化方式

                  逆向知识第七讲,三目运算符在汇编中的表现形式 一丶编译器优化方式 首先说一下编译器优化方式. 1.常量折叠 2.常量传播 3...

29780
来自专栏轮子工厂

5. 很“迷”的字符与字符串

最近一直在为自己的浏览量而担忧啦,都快被厂长大人约谈了……我真的有尽力在写稿子哦,所以也请各位老铁,如果觉得我的文章还不错就转发到朋友圈或者微信群之类的,让更多...

14320
来自专栏java一日一条

一个Java对象到底占用多大内存

大家可以用这个代码边看边验证,注意的是,运行这个程序需要通过javaagent注入Instrumentation,具体可以看原博客。我今天主要是总结下手动计算J...

8410
来自专栏SDNLAB

【一课专栏】解构2 - 明察YangInstanceIdentifier

屈原《离骚》中云:“路漫漫其修远兮,吾将上下而求索”,其实,学习软件编程,学习SDN技术也是一个路漫漫,上下求索的过程。

29920
来自专栏编程

Python入门白皮书#P01 Lists

文档: 我们以Google Python Exercises作为练习素材。 参考对应的文档 https://developers.google.com/edu/...

20860
来自专栏Brian

Python进阶教程(二)

概述 在上一篇博客中,我们介绍了Python进阶教程(一),还有一些新的技巧没有翻译完,我们下面来继续我们的翻译。 Intermediate Python 中译...

50380
来自专栏mukekeheart的iOS之旅

Java程序员面试宝典——重要习题整理

1、下面程序的输出结果是() public class Test { public static void main(String[] arg...

24190
来自专栏Pythonista

python中的函数

初中数学函数定义:一般的,在一个变化过程中,如果有两个变量x和y,并且对于x的每一个确定的值,y都有唯一确定的值与其对应,那么我们就把x称为自变量,把y称为因变...

18540
来自专栏前端菜鸟变老鸟

特定场景下的数据格式化(根据后台控制格式化的方式)

15530

扫码关注云+社区

领取腾讯云代金券