您的位置:首页 > 其它

06 多线程

2016-01-22 19:22 316 查看
06 多线程

###06.01_什么是线程

* 线程是程序执行的一条路径, 一个进程中可以包含多条线程

* 多线程并发执行可以提高程序的效率, 可以同时完成多项工作

###06.02_多线程并行和并发的区别

* 并行就是两个任务同时运行,就是甲任务进行的同时,乙任务也在进行。(需要多核CPU)

* 并发是指两个任务都请求运行,而处理器只能按受一个任务,就把这两个任务安排轮流进行,由于时间间隔较短,使人感觉两个任务都在运行。

###06.03_多线程(多线程程序实现的方式1)

* 1.继承Thread

* 定义类继承Thread

* 重写run方法,把新线程要做的事写在run方法中

* 创建线程对象

* 开启新线程, 内部会自动执行run方法

public class Demo2_Thread {

public static void main(String[] args) {

MyThread mt = new MyThread();//4,创建自定义类的对象

mt.start();
//5,开启线程

for(int i = 0; i < 3000; i++) {

System.out.println("bb");

}

}

}

class MyThread extends Thread {//1,定义类继承Thread

public void run() {//2,重写run方法

for(int i = 0; i < 3000; i++) {//3,将要执行的代码,写在run方法中

System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaaa");

}

}

}

###06.04_多线程(多线程程序实现的方式2)

* 2.实现Runnable

* 定义类实现Runnable接口

* 实现run方法,把新线程要做的事写在run方法中

* 创建自定义的Runnable的子类对象

* 创建Thread对象, 传入Runnable

* 调用start()开启新线程, 内部会自动调用Runnable的run()方法

public class Demo3_Runnable {

public static void main(String[] args) {

MyRunnable mr = new MyRunnable();//4,创建自定义类对象

//Runnable target = new MyRunnable();

Thread t = new Thread(mr);//5,将其当作参数传递给Thread的构造函数

t.start();
//6,开启线程

for(int i = 0; i < 3000; i++) {

System.out.println("bb");

}

}

}

class MyRunnable implements Runnable {//1,自定义类实现Runnable接口

@Override

public void run() {//2,重写接口Runnable的run方法

for(int i = 0; i < 3000; i++) {//3,将要执行的代码,写在run方法中

System.out.println("aaaaaaaaaaaa");

}

}

}

###06.05_多线程(两种方式的区别)

* 继承Thread

* 好处是:可以直接使用Thread类中的方法,代码简单

* 弊端是:如果已经有了父类,就不能用这种方法

* 实现Runnable接口

* 好处是:即使自己定义的线程类有了父类也没关系,因为有了父类也可以实现接口,而且接口是可以多实现的

* 弊端是:不能直接使用Thread中的方法需要先获取到线程对象后,才能得到Thread的方法,代码复杂

###06.06_多线程(匿名内部类实现线程的两种方式)

* 继承Thread类

new Thread() {//1,new 类(){}继承这个类

public void run() {//2,重写run方法

for(int i = 0; i < 3000; i++) {//3,将要执行的代码,写在run方法中

System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaaa");

}

}

}.start();

* 实现Runnable接口

new Thread( new Runnable(){//1,new 接口(){}实现这个接口

public void run() {//2,重写run方法

for(int i = 0; i < 3000; i++) {//3,将要执行的代码,写在run方法中

System.out.println("bb");

}

}

} ).start();

###06.07_多线程(休眠线程)

* Thread.sleep(毫秒,纳秒), 控制当前线程休眠若干毫秒 1秒= 1000毫秒 1秒 = 1000 * 1000 * 1000纳秒 1000000000

* 会有InterruptedException异常

###06.08_多线程(守护线程)

* setDaemon(), 设置一个线程为守护线程, 该线程不会单独执行, 当其他非守护线程都执行结束后, 自动退出

###06.09_多线程(加入线程)

* join(), 使当前线程暂停, 等待指定的线程执行结束后, 当前线程再继续

* join(int), 可以指定等待时间毫秒值,之后再继续执行交替执行

###06.10_多线程(设置线程的优先级)

* setPriority()设置线程的优先级

//t1.setPriority(1);
//传数字和常量都可以 ,1最小,5默认,10最大

//t2.setPriority(10);

t1.setPriority(Thread.MAX_PRIORITY);

t2.setPriority(Thread.MIN_PRIORITY);

###06.11_多线程(同步代码块)

* 1.什么情况下需要同步

* 当多线程并发, 有多段代码同时执行时, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作. 这时就需要同步.

* 如果两段代码是同步的, 那么同一时间只能执行一段, 在一段代码没执行结束之前, 不会执行另外一段代码.

* 2.同步代码块

* 使用synchronized关键字加上一个锁对象来定义一段代码, 这就叫同步代码块

* 多个同步代码块如果使用相同的锁对象, 那么他们就是同步的

public class Demo_同步代码块 {

public static void main(String[] args) {

final Print p = new Print();
//用final修饰

new Thread(){

public void run(){

for (int i = 0; i < 500; i++) {

p.print1();

}

}

}.start();

new Thread(){

public void run(){

for (int i = 0; i < 500; i++) {

p.print2();

}

}

}.start();

}

}

class Print{

Deemmoo d = new Deemmoo();

public void print1(){

synchronized(d){ //锁对象可以是任意对象,但是被锁的代码需要保证是同一把锁,所以不能用匿名对象

System.out.print("黑");

System.out.print("马");

System.out.print("程");

System.out.print("序");

System.out.print("员");

System.out.print("\r\n");

}

}

public void print2(){

synchronized(d){

System.out.print("你");

System.out.print("真");

System.out.print("的");

System.out.print("很");

System.out.print("美");

System.out.print("\r\n");

}

}

}

class Deemmoo{

}

###06.12_多线程(同步方法)

* 使用synchronized关键字修饰一个方法, 该方法中所有的代码都是同步的 //同步方法只需要在方法上加synchronized关键字即可

###06.13_多线程(线程安全问题)

* 多线程并发操作同一数据时, 就有可能出现线程安全问题

* 使用同步技术可以解决这种问题, 把操作数据的代码进行同步, 不要多个线程一起操作

###06.14_多线程(单例设计模式)

* 单例设计模式:保证类在内存中只有一个对象。

* 如何保证类在内存中只有一个对象呢?

* (1)控制类的创建,不让其他类来创建本类的对象。private

* (2)在本类中定义一个本类的对象。Singleton s;

* (3)提供公共的访问方式。 public static Singleton getInstance(){return s}

* 饿汉式和懒汉式的区别

* 1,饿汉式是空间换时间,懒汉式是时间换空间

* 2,在多线程访问时,饿汉式不会创建多个对象,而懒汉式有可能会创建多个对象

* 单例写法两种:

* (1)饿汉式 开发用这种方式。

//饿汉式

class Singleton {

//1,私有构造函数

private Singleton(){}

//2,创建本类对象

private static Singleton s = new Singleton();

//3,对外提供公共的访问方法

public static Singleton getInstance() {

return s;

}

public static void print() {

System.out.println("11111111111");

}

}

* (2)懒汉式 面试写这种方式。多线程的问题?

//懒汉式, 单例的延迟加载模式

class Singleton {

//1,私有构造函数

private Singleton(){}

//2,声明一个本类的引用

private static Singleton s;

//3,对外提供公共的访问方法

public static Singleton getInstance() {

if(s == null)

//线程1,线程2 当时多线程的时候可能出现多个对象

s = new Singleton();

return s;

}

public static void print() {

System.out.println("11111111111");

}

}

* (3)第三种格式

class Singleton {

private Singleton() {}

public static final Singleton s = new Singleton(); //final是最终的意思,被final修饰的变量不可以被更改

}

###06.15_多线程(线程间的通信注意的问题)

* 1,在同步代码块中,用哪个对象锁,就用哪个对象调用wait方法

* 2,为什么wait方法和notify方法定义在Object类中? 因为锁对象可以是任意对象,Object是所有的类的基类,所以wait方法和notify方法需要定义在Object这个类中

* 3,sleep方法和wait方法的区别?

* a,sleep方法必须传入参数,参数就是时间,时间到了自动醒来

wait方法可以传入参数也可以不传入参数,传入参数就是在参数的时间结束后等待,不传入参数就是直接等待

* b,sleep方法在同步函数或同步代码块中,不释放锁,睡着了也抱着锁睡,一直占用cpu.

wait方法在同步函数或者同步代码块中,释放锁

###06.16_多线程(线程的五种状态)

* 新建, 创建线程对象

start()

* 就绪, 就绪状态,有执行的资格,但没有执行权

抢到了cpu的执行权; 被其他的线程把cpu执行权抢走了

* 运行, 有执行资格和执行权

run()结束

stop()已经过去了

* 死亡, 线程对象变成垃圾

sleep()

wait()

* 阻塞,

###06.17_多线程(JDK1.5的新特性互斥锁)

* 1.同步

* 使用ReentrantLock类的lock()和unlock()方法进行同步

* 2.通信

* 使用ReentrantLock类的newCondition()方法可以获取Condition对象

* 需要等待的时候使用Condition的await()方法, 唤醒的时候用signal()方法

* 不同的线程使用不同的Condition, 这样就能区分唤醒的时候找哪个线程了

* 3.代码实现略
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: