1 概念
*1 线程的概念
* 进程:电脑中正在运行的程序
* 线程:正在运行的程序中正在执行的代码块
* 线程是进程的基本单位/执行单元
* 进程为线程提供执行空间
* 实例: 正在生产的工厂---进程
* 正在生产的工厂中正在运行的流线线---线程
* 多线程/线程并发:一个程序中有多个代码块同时执行
2 垃圾回收机制
*2 垃圾回收机制:
* jvm会不定时的启动垃圾回收器对象 ,垃圾回收器会根据对象是否存在更多引用
* 来判断此对象是否是垃圾 如果是垃圾就调用对象的finalize方法 来销毁对象 释放内存
* 程序员可以通过System.gc()来主动启动垃圾回收器
*
* 专门有一个线程:垃圾回收的线程
* 和主(main---执行main方法中的代码)线程是不同的线程
package day15_thread ;
public class Demo01 {
public static void main ( String [ ] args) {
for ( int i = 0 ; i < 20 ; i++ ) {
new Test01 ( ) ;
}
System . gc ( ) ;
for ( int i = 0 ; i < 100 ; i++ ) {
for ( int j = 0 ; j < 100 ; j++ ) {
if ( i% 5 == 0 && j== 10 ) {
System . out. println ( "主方法的代码:::i=" + i) ;
}
}
}
}
public static Object hehe ( ) {
Object obj= new Object ( ) ;
return obj;
}
}
class Test01 {
private static int n= 0 ;
public final int num;
{ n++ ; num= n; System . out. println ( "第" + num+ "个对象被创建了!!!" ) ; }
public String toString ( ) {
return "Test01 [num=" + num + "]" ;
}
@Override
protected void finalize ( ) throws Throwable {
System . out. println ( this . num+ ":::finalize方法被调用!::::" ) ;
super . finalize ( ) ;
}
}
3 多线程原理
*多线程原理:cpu在同一个时间轮片(时间单位:大概20hm)内只执行一个线程的代码
* 时间轮片到期 就在等待的多个线程之间进行随机切换
4 创建线程方式1
package day15_thread ;
public class Demo02CreateThread {
public static void main ( String [ ] args) {
MyThread021 mt1= new MyThread021 ( ) ;
mt1. start ( ) ;
for ( int i = 0 ; i < 50 ; i++ ) {
Thread t= Thread . currentThread ( ) ;
System . out. println ( t. getName ( ) + "+++++++++++++++++++i=" + i) ;
try { Thread . sleep ( 30 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
}
class MyThread021 extends Thread {
public void run ( ) {
for ( int i = 0 ; i < 50 ; i++ ) {
Thread t= Thread . currentThread ( ) ;
System . out. println ( t. getName ( ) + "-----i=" + i) ;
try { Thread . sleep ( 30 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
}
5 Thread的常用方法
* Thread 类的方法:
* 构造方法:
* Thread ( ) :线程名字是默认的:Thread - index
* Thread ( String name) : 指定线程名字
* Thread ( Runnable target) :
* Thread ( Runnable target, String name)
* 普通方法:
* String getName ( ) :获取线程名字
* void setName ( String name) :设置线程名字
* static Thread currentThread ( ) :获取当前线程对象
* void run ( ) :封装线程任务:线程启动 jvm自动调用线程的run方法
* void start ( ) :线程启动:jvm会在内存中为当前线程开辟执行空间 执行其线程任务
* static void sleep ( long millis) :线程休眠
6 练习
三个线程打印不同的字符:三个类
package day15_thread ;
public class LianXi01 {
public static void main ( String [ ] args) {
MyThread01SZ sz1= new MyThread01SZ ( ) ; sz1. setName ( "数字::" ) ;
MyThread01XX sz2= new MyThread01XX ( ) ; sz2. setName ( "xiaoxie::::" ) ;
MyThread01DX sz3= new MyThread01DX ( ) ; sz3. setName ( "DAXIE::::::::::" ) ;
sz1. start ( ) ; sz2. start ( ) ; sz3. start ( ) ;
}
}
class MyThread01SZ extends Thread {
public void run ( ) {
String name= Thread . currentThread ( ) . getName ( ) ;
for ( int i = 0 ; i < 50 ; i++ ) {
char c= ( char ) ( Math . random ( ) * 10 + '0' ) ;
System . out. println ( name+ "::::" + c) ;
try { Thread . sleep ( 10 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
}
class MyThread01XX extends Thread {
public void run ( ) {
String name= Thread . currentThread ( ) . getName ( ) ;
for ( int i = 0 ; i < 50 ; i++ ) {
char c= ( char ) ( Math . random ( ) * 26 + 'a' ) ;
System . out. println ( name+ "::::" + c) ;
try { Thread . sleep ( 10 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
}
class MyThread01DX extends Thread {
public void run ( ) {
String name= Thread . currentThread ( ) . getName ( ) ;
for ( int i = 0 ; i < 50 ; i++ ) {
char c= ( char ) ( Math . random ( ) * 26 + 'A' ) ;
System . out. println ( name+ "::::" + c) ;
try { Thread . sleep ( 10 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
}
三个线程打印不同的字符:一个类
package day15_thread ;
public class LianXi02 {
public static void main ( String [ ] args) {
MyThread01 sz1= new MyThread01 ( 10 , '0' ) ; sz1. setName ( "数字::" ) ;
MyThread01 sz2= new MyThread01 ( 26 , 'a' ) ; sz2. setName ( "xiaoxie::::" ) ;
MyThread01 sz3= new MyThread01 ( 26 , 'A' ) ; sz3. setName ( "DAXIE::::::::::" ) ;
sz1. start ( ) ; sz2. start ( ) ; sz3. start ( ) ;
}
}
class MyThread01 extends Thread {
int fw;
char startChar;
MyThread01 ( int fw, char startChar) { this . fw= fw; this . startChar= startChar; }
public void run ( ) {
String name= Thread . currentThread ( ) . getName ( ) ;
for ( int i = 0 ; i < 50 ; i++ ) {
char c= ( char ) ( Math . random ( ) * fw+ startChar) ;
System . out. println ( name+ "::::" + c) ;
try { Thread . sleep ( 10 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
}
7 创建线程方式2
步骤
public class Demo04CreateThread {
public static void main ( String [ ] args) {
MyImp1 m1= new MyImp1 ( ) ;
Thread t1= new Thread ( m1, "线程11" ) ;
Thread t2= new Thread ( m1, "线程2222" ) ;
t1. start ( ) ;
t2. start ( ) ;
Thread t3= new Thread ( "线程333" ) ;
t3. start ( ) ;
}
}
class MyImp1 implements Runnable {
public void run ( ) {
for ( int i = 0 ; i < 20 ; i++ ) {
System . out. println ( Thread . currentThread ( ) . getName ( ) + ":::" + i+ ":::" + ( int ) ( Math . random ( ) * 100 ) ) ;
try { Thread . sleep ( 10 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
}
模拟
jvm怎么智能判断 运行Thread类的run方法还是运行Thread类关联的Runnable的run方法
class MyThreadDemo {
private MyRunnableDemo r;
MyThreadDemo ( ) { }
MyThreadDemo ( MyRunnableDemo r) { this . r= r; }
public void run ( ) {
System . out. println ( "Thread类的run方法!!!" ) ;
}
public void start ( ) {
if ( r!= null ) {
r. run ( ) ;
} else {
this . run ( ) ;
}
}
}
interface MyRunnableDemo {
public void run ( ) ;
}
比较
* 两种创建线程的方式之间作比较:第二种方式更优:
* 1 :java只支持类与类的单继承 方式1 继承了Thread 无法再扩展
* 方式2 实现Runnable 接口 不影响继承其他类 还可以再扩展
* 2 : 实现Runnable 接口的实现类对象 是对线程任务的封装 符合java完全面向对象的思想
8 练习
交作业
package day15_thread ;
public class LianXi03 {
public static void main ( String [ ] args) {
Teacher03 tt= new Teacher03 ( ) ;
StudentImp imp1= new StudentImp ( ) ;
StudentImp imp2= new StudentImp ( ) ;
StudentImp imp3= new StudentImp ( ) ;
StudentImp imp4= new StudentImp ( ) ;
StudentImp imp5= new StudentImp ( ) ;
imp1. t= tt; imp2. t= tt; imp3. t= tt; imp4. t= tt; imp5. t= tt;
Thread t11= new Thread ( imp1, "张三" ) ;
Thread t12= new Thread ( imp2, "张三丰" ) ;
Thread t13= new Thread ( imp3, "张三太郎" ) ;
Thread t14= new Thread ( imp4, "三" ) ;
Thread t15= new Thread ( imp5, "3" ) ;
t11. start ( ) ; t12. start ( ) ; t13. start ( ) ; t14. start ( ) ; t15. start ( ) ;
}
}
class Teacher03 {
int num;
}
class StudentImp implements Runnable {
Teacher03 t;
public void run ( ) {
for ( int i = 1 ; i <= 4 ; i++ ) {
System . out. println ( Thread . currentThread ( ) . getName ( ) + ":::::正在提交作业::" + i) ;
t. num++ ;
try { Thread . sleep ( 10 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
System . out. println ( "老师的作业本书是:::" + t. num) ;
}
}
}
卖票
package day15_thread ;
public class LianXi04 {
public static void main ( String [ ] args) {
WindowImp imp= new WindowImp ( ) ;
imp. t= new Train ( ) ;
new Thread ( imp, "窗口1111" ) . start ( ) ;
new Thread ( imp, "窗口11112222" ) . start ( ) ;
new Thread ( imp, "窗口111133333333" ) . start ( ) ;
new Thread ( imp, "窗口1111444444444444" ) . start ( ) ;
}
}
class Train {
int num= 100 ;
}
class WindowImp implements Runnable {
Train t;
public void run ( ) {
while ( t. num> 0 ) {
try { Thread . sleep ( 100 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
System . out. println ( Thread . currentThread ( ) . getName ( ) + ":::::卖票::票号是:::" + t. num) ;
t. num-- ;
}
}
}
9 join
join
package day15_thread ;
public class Demo05Join {
public static void main ( String [ ] args) {
Demo05Imp1 imp1= new Demo05Imp1 ( ) ;
Thread t1= new Thread ( imp1, "线程1" ) ;
Thread t2= new Thread ( new Demo05Imp2 ( ) , "线程2222" ) ;
imp1. t= t2;
t1. start ( ) ;
t2. start ( ) ;
for ( int i = 0 ; i < 50 ; i++ ) {
int n= ( int ) ( Math . random ( ) * 10 ) ;
System . out. println ( Thread . currentThread ( ) . getName ( ) + ":::::::" + i+ "::::::" + n) ;
try { Thread . sleep ( 10 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
}
class Demo05Imp1 implements Runnable {
Thread t;
public void run ( ) {
for ( int i = 0 ; i < 50 ; i++ ) {
int n= ( int ) ( Math . random ( ) * 10 ) ;
System . out. println ( Thread . currentThread ( ) . getName ( ) + ":::" + i+ ":::" + n) ;
if ( n== 5 ) {
try { t. join ( ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
try { Thread . sleep ( 10 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
}
class Demo05Imp2 implements Runnable {
public void run ( ) {
for ( int i = 0 ; i < 50 ; i++ ) {
System . out. println ( Thread . currentThread ( ) . getName ( ) + ":::::" +
i+ "::::::" + ( int ) ( Math . random ( ) * 10 + 10 ) ) ;
try { Thread . sleep ( 10 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
}
join死锁
两个线程互相调用对方的join方法
package day15_thread ;
public class Demo06JoinDieLock {
public static void main ( String [ ] args) {
MyPrintImp t1= new MyPrintImp ( ) ;
MyPrintImp t2= new MyPrintImp ( ) ;
t1. t= t2;
t2. t= t1;
t1. joinChar= '0' ;
t2. joinChar= '5' ;
t1. setName ( "线程1号" ) ;
t2. setName ( "线程2222222222222号" ) ;
t1. start ( ) ;
t2. start ( ) ;
}
}
class MyPrintImp extends Thread {
Thread t;
char joinChar;
public void run ( ) {
for ( int i = 1 ; i <= 50 ; i++ ) {
try { Thread . sleep ( 100 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
char c= ( char ) ( Math . random ( ) * 10 + '0' ) ;
System . out. println ( Thread . currentThread ( ) . getName ( ) + ":::" + i+ ":::::" + c) ;
if ( t!= null && c== joinChar) {
try { t. join ( ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
}
}
10 线程同步
线程安全问题
* 分析:出现情况:1 票号重复 2 有负票存在
* 票号重复的原因:
* a线程在打印完num ( 100 ) 后 没有立刻执行num--
* cpu的执行权随机给了另外一个线程b b线程也是先打印num ( 100 ) b
*
*
* 负票的存在原因:
* 假设num= 1 并且此时4 个线程都到达while ( num> 0 ) 位置
* a线程判断num> 0 成立 进来后需要休眠 此时时间轮片到期 随机到b线程
* b线程判断num> 0 成立 进来后需要休眠 假设此时时间轮片也到期 随机到c线程
* c线程判断num> 0 成立 进来后需要休眠 假设此时时间轮片还到期 随机到d线程
* d线程判断num> 0 成立 也进来
* 后期打印:num= 1 0 - 1 - 2 四张票被卖
*
* 多线程中:由于多个线程操作同一个数据 出现前后数据不一致 结果无法预期的现象-- - 线程安全问题
* 线程安全问题前提条件:
* 1 必须时多线程
* 2 必须有共享数据
* 3 必须有多个语句操作共享数据:一个线程在多个语句操作共享数据期间 别的线程对共享数据进行了修改
同步代码块
package day16_thread_xml ;
public class Demo01Sync {
public static void main ( String [ ] args) {
WindowImp imp1 = new WindowImp ( ) ;
Train t= new Train ( ) ;
imp1. t = t;
new Thread ( imp1, "窗口1111" ) . start ( ) ;
new Thread ( imp1, "窗口11112222" ) . start ( ) ;
new Thread ( imp1, "窗口111133333333" ) . start ( ) ;
new Thread ( imp1, "窗口1111444444444444" ) . start ( ) ;
}
}
class Train {
int num = 100 ;
}
class WindowImp implements Runnable {
Train t;
public void run ( ) {
while ( true ) {
synchronized ( t) {
if ( t. num<= 0 ) {
break ;
}
try { Thread . sleep ( 10 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
System . out. println ( Thread . currentThread ( ) . getName ( ) + ":::::卖票::票号是:::" + t. num) ;
try { Thread . sleep ( 20 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
t. num-- ;
}
try { Thread . sleep ( 50 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
}
同步代码块实现死锁
通过同步代码块实现死锁:两个同步代码块嵌套,两个线程的内外锁交替
package day16_thread_xml ;
public class Demo02SyncDieLock {
public static void main ( String [ ] args) {
MyThread02 t1= new MyThread02 ( ) ;
MyThread02 t2= new MyThread02 ( ) ;
Object a= new Object ( ) ;
Object b= new Object ( ) ;
t1. wai= a; t1. nei= b;
t2. wai= b; t2. nei= a;
t1. setName ( "线程1号::" ) ;
t2. setName ( "线程2号:::::" ) ;
t1. start ( ) ;
t2. start ( ) ;
}
}
class MyThread02 extends Thread {
Object wai, nei;
public void run ( ) {
while ( true ) {
synchronized ( wai) {
System . out. println ( Thread . currentThread ( ) . getName ( ) + "拿到其外锁+++++" + wai) ;
synchronized ( nei) {
System . out. println ( Thread . currentThread ( ) . getName ( ) + "拿到其内锁+++++++++" + nei) ;
}
System . out. println ( Thread . currentThread ( ) . getName ( ) + "释放内锁---------" + nei) ;
}
System . out. println ( Thread . currentThread ( ) . getName ( ) + "释放外锁-----" + wai) ;
}
}
}
11 wait和notify,notifyAll
package day16_thread_xml ;
public class Demo03WaitNotify {
public static void main ( String [ ] args) {
ShaoBing s= new ShaoBing ( ) ;
CreateShb c= new CreateShb ( ) ; c. setName ( "武大郎" ) ;
CreateShb c2= new CreateShb ( ) ; c2. setName ( "武松" ) ;
EatShb e= new EatShb ( ) ; e. setName ( "西门庆" ) ;
EatShb e2= new EatShb ( ) ; e2. setName ( "潘金莲" ) ;
c. shb= s; e. shb= s; c2. shb= s; e2. shb= s;
c. start ( ) ; e. start ( ) ; c2. start ( ) ; e2. start ( ) ;
}
}
class ShaoBing {
int num;
boolean b= false ;
}
class CreateShb extends Thread {
ShaoBing shb;
public void run ( ) {
while ( true ) {
synchronized ( shb) {
if ( ! shb. b) {
shb. num++ ;
System . out. println ( Thread . currentThread ( ) . getName ( ) + "开始做烧饼::" + shb. num) ;
try { Thread . sleep ( 10 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
System . out. println ( Thread . currentThread ( ) . getName ( ) + "烧饼做好了::" + shb. num) ;
shb. b= true ;
shb. notifyAll ( ) ;
}
try { shb. wait ( ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
try { Thread . sleep ( 500 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
}
class EatShb extends Thread {
ShaoBing shb;
public void run ( ) {
while ( true ) {
synchronized ( shb) {
if ( shb. b) {
System . out. println ( Thread . currentThread ( ) . getName ( ) + "开始吃烧饼:::::" + shb. num) ;
try { Thread . sleep ( 10 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
System . out. println ( Thread . currentThread ( ) . getName ( ) + "烧饼吃完了:::::" + shb. num) ;
shb. b= false ;
shb. notifyAll ( ) ;
}
try { shb. wait ( ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
try { Thread . sleep ( 2 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
}
12 同步方法
同步实例方法
package day16_thread_xml ;
public class Demo04SyncMethod {
public static void main ( String [ ] args) {
Person p= new Person ( ) ;
SetThread set= new SetThread ( ) ; set. p= p;
PrintThread print= new PrintThread ( ) ; print. p= p;
set. start ( ) ;
print. start ( ) ;
}
}
class Person {
String name;
char sex;
public synchronized void set ( ) {
if ( Math . random ( ) < 0.5 ) {
this . sex= '女' ;
this . name= "rose" + ( int ) ( Math . random ( ) * 100 + 1 ) ;
} else {
this . sex= '男' ;
this . name= "张三" + ( int ) ( Math . random ( ) * 100 + 1 ) ;
}
}
}
class SetThread extends Thread {
Person p;
public void run ( ) {
while ( true ) {
if ( Math . random ( ) > 0.5 ) {
p. set ( ) ;
} else {
synchronized ( p) {
if ( Math . random ( ) < 0.5 ) {
p. sex= '女' ;
p. name= "rose" + ( int ) ( Math . random ( ) * 100 + 1 ) ;
} else {
p. sex= '男' ;
p. name= "张三" + ( int ) ( Math . random ( ) * 100 + 1 ) ;
}
}
}
try { Thread . sleep ( 100 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
}
class PrintThread extends Thread {
Person p;
public void run ( ) {
while ( true ) {
synchronized ( p) {
System . out. println ( p. sex+ ":::" + p. name) ;
try { Thread . sleep ( 50 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
try { Thread . sleep ( 50 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
}
同步静态方法
package day16_thread_xml ;
public class Demo04SyncMethod2 {
public static void main ( String [ ] args) {
Person2 p= new Person2 ( ) ;
SetThread2 set= new SetThread2 ( ) ; set. p= p;
PrintThread2 print= new PrintThread2 ( ) ; print. p= p;
set. start ( ) ;
print. start ( ) ;
}
}
class Person2 {
String name;
char sex;
}
class SetThread2 extends Thread {
Person2 p;
public void run ( ) {
while ( true ) {
if ( Math . random ( ) > 0.5 ) {
set ( p) ;
} else {
synchronized ( SetThread2 . class ) {
if ( Math . random ( ) < 0.5 ) {
p. sex= '女' ;
try { Thread . sleep ( 20 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
p. name= "rose" + ( int ) ( Math . random ( ) * 100 + 1 ) ;
} else {
p. sex= '男' ;
try { Thread . sleep ( 20 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
p. name= "张三" + ( int ) ( Math . random ( ) * 100 + 1 ) ;
}
}
}
try { Thread . sleep ( 50 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
public static synchronized void set ( Person2 p) {
if ( Math . random ( ) < 0.5 ) {
p. sex= '女' ;
try { Thread . sleep ( 20 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
p. name= "rose" + ( int ) ( Math . random ( ) * 100 + 1 ) ;
} else {
p. sex= '男' ;
try { Thread . sleep ( 20 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
p. name= "张三" + ( int ) ( Math . random ( ) * 100 + 1 ) ;
}
}
}
class PrintThread2 extends Thread {
Person2 p;
public void run ( ) {
while ( true ) {
synchronized ( SetThread2 . class ) {
System . out. println ( p. sex+ ":::" + p. name) ;
try { Thread . sleep ( 20 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
try { Thread . sleep ( 20 ) ; } catch ( Exception e) { throw new RuntimeException ( e) ; }
}
}
}