您的位置:首页 > 其它

线程

2015-12-01 23:51 211 查看

进程和线程概念

进程:相对于系统来讲(Win Linux Mac),独立的内存空间,并发性,动态性

线程:相对于进程来讲,是进程内部的一个执行单元,内部单一的执行单元,顺序控制流程,共享进程资源

创建线程

1.继承Thread类,复写其run()方法,调用start()方法,启动线程

MyThread  t = new MyThread ();
t.start();


2.实现Runnable接口,实现其run()方法,调用start()方法

MyThread mt =   new MyThread ();
Thread t  =   new Thread(mt);
t.start();


两种创建进程方法的比较

继承Thread类方式的多线程

- 优势:编写简单

- 劣势:无法继承其它父类

实现Runnable接口方式的多线程

- 优势:可以继承其它类,多线程可共享同一个Thread对象

- 劣势:编程方式稍微复杂,如果需要访问当前线程,需要调用Thread.currentThread()方法

调用start()方法启动线程和直接调用run()方法的区别

调用start()方法,会申请新的线程,开辟新的线程空间去执行run()方法中的内容

调用run()方法,只是由当前线程去调用run()方法,不会创建新的线程,仅将其当成一个普通方法调用

多线程的优势(重点)

多线程使系统空转时间减少,提高CPU利用率

进程间不能共享内存,但线程之间共享内存非常容易

使用多线程实现多任务并发比多进程的效率高

Java语言内置多线程功能支持,简化了Java的多线程编程

线程状态



新生 创建新的线程对象

运行 调用start()方法

阻塞

1.sleep(long time) 睡眠time毫秒后,自动唤醒继续运行

2.join()加入 A线程加入到B线程,B线程等待A线程运行完毕再继续向下执行

3.yield()暂停瞬间,然后继续执行

死亡 整个线程的run()方法的代码块运行完毕

线程锁

synchronization(){ }同步代码块 多个线程中存在使用同一把锁的代码块,多个线程会抢这一把锁,抢到的进入同步代码块,剩下的线程全在外面阻塞,阻塞到进入的线程运行完,该线程会释放锁,所有阻塞的线程继续开始抢锁。

同步方法 public synchronized void xxx (){ },同步方法的锁,就是锁住的对象就是调用该方法的对象

注意 :在拥有同步方法的类中,锁住的是该类的实例化的对象

线程同步的必要性



线程间通信

wait()和notify()

当执行了wait()方法后,本线程终止,将锁释放给正在等待该锁的线程

当执行了notify()方法后,线程会唤醒正在等待该锁的对象,但是唤醒后不是立即执行,而是等调用notify()方法的线程执行完同步代码块之后,才开始抢占执行。

Timer

定时器的使用

首先要实例化Timer对象,

然后要重写一个类继承TimerTask类,在复写其中的run()方法

然后调用Timer()对象的schedule(TimerTask task, long delay, long period)

第一个参数是继承TimerTask类的实例化对象

第二个参数是延时多久开始执行其run()方法

第三个参数是run()方法循环的间隔时间

public class Test {
public static void main(String[] args) {
Timer timer=new Timer();
timer.schedule(new MyTimerTask(), 2000 ,500);
}
}

public class MyTimerTask extends TimerTask{
private int i=0;
public void run() {
System.out.println("正在计时:"+i++);
}
}


反射详解

反射就是可以通过对象实例或者类名来获取Class对象,通过Class对象的各种方法,可以获得该类的各种信息,包括属性,方法,构造器,返回值类型,属性类型等等。

Class 类的抽象 Person Dog Car

Field 属性的抽象

Method 方法的抽象

Constructor 构造器的抽象



可以通过反射的机制,给对象中的属性进行赋值操作

public class ReflectionTest {
public static void main(String[] args) {
Person zhangsan=new Person();
System.out.println(zhangsan.getName());
//此Person中不存在一个可以访问方法去修改名字
//可以使用反射去修改zhangsan这个对象的name
//1得到Person的Class对象
Class<Person> zhangsanClass=(Class<Person>) zhangsan.getClass();
try {
//2得到Person类中名称是name的字段
Field name=zhangsanClass.getDeclaredField("name");
//3取消反射时的java语言访问限制
name.setAccessible(true);
//4使用field修改zhangsan的name的值,因为Person中的name是private的,所以会报错,其他修饰符的话不会报错
name.set(zhangsan, "张三");
//5重新打开反射时的java语言访问限制,以后访问还要检查
name.setAccessible(false);
System.out.println(zhangsan.getName());
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}

public class Person {
private String name ;//zheshishenme a
private String sex;
public String getName() {
return name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}

}


设计模式

Dao模式

只有属性和set get方法

单例模式

在要单例化的类中

① 私有化构造器,不允许外部使用new关键字创建对象

② 声明一个静态的私有的Person对象

③ 提供一个静态的公有的同步方法供外部访问,返回值类型是该类 为什么使用synchroized防止多个线程同时访问这个方法 静态同步方法的锁是指的类本身

④ 在该方法中添加限制

public class Person {
private String name;
private String sex;
//创建一个静态的私有的该类对象,声明为静态只能有一个这个对象的实例
private static Person person;

//私有化构造器
private Person() {
}
//创建一个共有的静态的同步方法,声明为同步方法可以限制多个线程同时访问的问题,声明为静态可以通过类名调用
public synchronized static Person newInstance() {
//在其中添加限制,若不为空,就实例化对象,否则仅返回其对象
if (person==null) {
person=new Person();
}
return person;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}

public class Test {
//所有输出的内容hashcode是一样的,表示是同一个对象
public static void main(String[] args) {
Person zhangsan=Person.newInstance();
System.out.println(zhangsan);

Person lisi=Person.newInstance();
System.out.println(lisi);

new Thread(new Runnable() {
public void run() {
Person wangwu=Person.newInstance();
System.out.println(wangwu);
}
}).start();

new Thread(new Runnable() {
public void run() {
Person zhaoliu=Person.newInstance();
System.out.println(zhaoliu);
}
}).start();
}
}


简单工厂模式

创建一个工厂,使用这个工厂创建这个类的对象

创建一个配置文件properties格式,用Properties类从中读取类的信息,根据类的信息用Class的forName(String str),获取累的对象,

再用该对象实例化要生成的对象实例

要改变生成的对象实例时候,就不用重新编译代码,仅仅修改配置文件的类的信息就可以了

另外如果要扩展程序的话,对源代码基本不用改变,直接生成你要添加的类的代码即可

public class Person {
public void speak() {
System.out.println("人类会说话");
}
}

public class Teacher extends Person{
@Override
public void speak() {
System.out.println("老师会讲课");
}
}

public class PersonFactory {
public Person newInstance() {
Person person=null;
Properties pro=new Properties();
try {
//解析配置文件
pro.load(new FileInputStream("config.properties"));
//从配置文件中读取类的信息
String str=pro.getProperty("classname");
//Class类根据类名生成Class的对象
Class name=Class.forName(str);
//由Class对象生成对应类的实例
person=(Person) name.newInstance();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return person;
}
}

public class Test {
public static void main(String[] args) {
PersonFactory factory=new PersonFactory();
Person person=factory.newInstance();
//根据生成对象的不同,输出相应改变
person.speak();
}
}


配置文件如下



知识漏洞

static

在一个类中,static修饰的类的属性,不管实例化多少个对象,该属性都只有一个,并且对每一个实例化对象共享。

PrintWriter

print()和println()的区别

- print()仅仅是打印输出

- println()打印输出,并且终止当前行的输出
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: