1.创建线程的方法
第一种:继承Thread类
a.定义一个类,继承Thread类.
b.重写run方法,将需要执行的代码,写入到run内部.
c.创建Thread的子类对象.
d.调用start()开启线程
第二种:实现Runnable接口
a.定义一个类,实现Runnable接口
b.重写run方法,将需要执行的代码,写入到run内部.
c.创建Runnable的子类对象.
d.创建Thread类的对象,将Runnable的实现类对象传递给他.
e.调用Thread类中的start()方法.
第三种:线程池
待续。。。
注:继承Thread类/实现Runnable接口,都是为了重写run()方法,run()方法只是普通方法,只有Thread类的start()方法,才是开启一个新线程的方法,start()方法开启新线程后会默认调用线程的run()方法。
2.Thread类的常用方法
Thread.currentThread() 返回当前正在执行的线程对象
Thread.setName(String name) 设置线程名字
Thread.getName() 获取线程名字
Thread.sleep(long millis) 睡眠固定时间
3.继承Thread类和实现Runnable接口的优缺点
实现Thread类:
可以使用Thread类的方法
继承Runnable接口:
避免了类单继承的局限性
增强了程序的扩展性,降低了程序的耦合性。把设置线程任务和开启新线程进行了分离
4.线程数据共享
多线程操作同一个实体对象
无论这个对象是Runnable接口的实现类,还是单独分装的一个对象,都是为了将共享数据
或者是方法存入同一个类中,来创建一个对象,以便多线程来操作一个实体对象。
问题:多线程安全问题
5.解决多线程安全问题的方法
同步代码块(synchronized)
synchronized(锁对象){
可能会出现线程安全问题的代码(访问了共享数据的代码)
}
注:同步代码块中的锁对象可以是任意一个,但是必须保证多线程使用的是同一个锁。
同步方法
修饰符 synchronized 返回值类型 方法名(参数列表){
可能会出现线程安全问题的代码(访问了共享数据的代码)
}
注:同步方法的锁默认为这个类的字节码
Lock锁
ReentrantLock类,lock(),unlock()
6.Object类的wait()方法和notify()方法
wait() 等待
wait(long millis) 等待固定时间
notify() 随机唤醒此对象监视器上一个等待的线程
notifyAll() 唤醒此对象监视器上所有等待的线程
注:
wait()方法和notify()方法:
必须写在同步代码块中(锁),wait()和notify()执行时都要获取锁
而且使用同步对象锁才能调用,不是锁对象调用相当于没有锁一样,无法获取锁。
否则,java.lang.IllegalMonitorStateException
wait()方法和sleep()方法的区别:
wait()方法,等待时释放锁
sleep()方法,睡眠时不释放锁
7.线程的状态
新建
阻塞
运行
计时等待
无限等待
死亡