一、先简单描叙一下创建线程的方式通过继承Thread:
(1)定义一个类继承Thread类
(2)覆盖Thread类中的run方法
(3)直接创建Thread的子类对象线程
(4)调用start方法开启线程并调用线程的任务run方法执行
二、run方法和start方法的区别
1.start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码:
通过调用Thread类的start()方法来启动一个线程,
这时此线程是处于就绪状态,
并没有运行。
然后通过此Thread类调用方法run()来完成其运行操作的,
这里方法run()称为线程体,
它包含了要执行的这个线程的内容,
Run方法运行结束,
此线程终止,
而CPU再运行其它线程,
2.run()方法当作普通方法的方式调用,程序还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码:
而如果直接用Run方法,
这只是调用一个方法而已,
程序中依然只有主线程--这一个线程,
其程序执行路径还是只有一条,
这样就没有达到写线程的目的。
举例说明一下:
记住:线程就是为了更好地利用CPU,
提高程序运行速率的!
在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM实习在就是在操作系统中启动了一个进程。
描述实现Runnable接口
(一)创建一个类,实现Runnable接口
(二)复写Runnable里面的run方法
(三)实例化这个类,调用start方法,此时线程开启,就执行该线程的run方法
实现Runnable接口的好处如下:
1.避免了java里面的单继承问题
2.适合多个相同的程序代码的线程去处理同一个资源
3.增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
一、产生线程安全的原因
(1)多个线程在操作共享数据
(2)操作共享数据的线程代码有多条
结论:当一个线程在执行操作共享数据的多条代码过程中,其他线程参与运算,就会导致线程安全问题的产生。
二、解决方案:同步锁,同步锁分为两种如下:
(1)同步锁代码块
(2)同歩锁函数
同步锁函数和同步代码块的区别:
①同步函数的锁是固定的this;
②同步代码块的锁是任意的对象;
③静态的同步函数使用的锁是该函数所属字节码文件对象,可以用getClass()方法获取,也可以用当前类名.class获取;
(3)使用同歩锁的前提:必须有多个线程并同时使用同一个锁;三、死锁原因
(1)同步锁嵌套
(2)线程间的通讯,多个线程在处理同一个资源,但任务却不同
四、等待/唤醒机制
(1)wait();让线程处于冻结状态,被wait的线程会被存储到线程池中;
(2)notify();唤醒线程池中一个线程(任意);
(3)notifyAll();唤醒线程池中的所有线程;
总结:这些方法都必须能定义在同步锁中,因为这些方法是用于操作线程状态的方法,必须能要明确到底操作的是哪个锁上的线程
为什么操作线程的方法wait notify notifyAll定义在了Object类中?
因为这些方法是监视器的方法。监视器其实就是锁。锁可以是任意的对象,任意的对象调用的方式一定定义在Object类中。
五、示例如下:
资源类:
输入类:
输出类:
测试类: