06 多线程

来源:互联网 发布:159素食全餐淘宝好便宜 编辑:程序博客网 时间:2024/06/01 18:20
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.代码实现略
0 0
原创粉丝点击