---------------------- ASP.Net+Android+IO开发S、.Net培训、期待与您交流! ------------------------
多线程
1. 多线程:如果一个程序有多条执行路径,这就是一个多线程的程序。
进程:正在执行的程序。 线程:程序的执行路径。执行单元。
举例:360管理界面,迅雷下载。
jvm的启动是多线程的因为它至少启动了main线程和垃圾回收线程。
2. 线程的四种状态
被创建--start()-->运行--sleep()/wait()-->冻结---->消亡
被创建--stop()-->消亡 冻结--notify()/notify()-->运行
运行-->run()/stop()-->消亡
sleep方法需要指定睡眠时间,单位是毫秒。
一个特殊的状态:就绪。具备了执行资格,但是还没有获取资源。
3. 线程的创建
创建线程方式一
(1) 继承Thread类
(2) 子类覆盖父类中的run方法,将线程运行的代码存放在run中。
(3) 建立子类对象的同时线程也被创建。
(4) 通过调用start方法开启线程。
创建线程方式二
(1) 实现Runnable接口
(2) 子类覆盖接口中的run方法。
(3) 通过Thread类创建线程,
并将实现了Runnable接口的子类对象作为参数传递给Thread类的构造函数。
(4) Thread类对象调用start方法开启线程。
run()和start()的区别:
run()里面封装的是线程执行的代码,如果直接调用,是普通方法调用。
start()做了两件事情:启动了线程,调用了run()方法。
要把自定义的类对象作为Thread类对象的构造参数传递的原因:
因为自定义的类它没有start()方法,只有Thread类有。
而如果单独创建Thread类的对象使用。那么,
最终使用的run方法默认情况下跟自定义的类对象无关。
为了让Thread类调用run()是自定义类里面的,所以,我们把它作为参数传递。
4. 线程安全问题
导致安全问题的出现的原因:多个线程访问出现延迟。线程随机性。
注:线程安全问题在理想状态下,不容易出现,
但一旦出现对软件的影响是非常大的。
判断一段程序有没有线程安全问题的依据:
(1) 有没有共享数据
(2) 有没有多条语句操作共享数据
(3) 是否是被多个线程访问
线程安全问题的解决
(1) 同步代码块
synchronized(对象) //锁对象:任意对象 { 需要被同步的代码; }
(2) 同步方法
在方法修饰用synchronized关键字。锁对象:this
(3) 静态同步方法: 锁对象为当前类的Class文件对象。
5. 同步(synchronized)及特点
格式:synchronized(对象){ 需要同步的代码;}
同步可以解决安全问题的根本原因就在那个对象上。
该对象如同锁的功能。
同步的前提:同步需要两个或者两个以上的线程。多个线程使用的是同一个锁。
未满足这两个条件,不能称其为同步。
同步的弊端:当线程相当多时,因为每个线程都会去判断同步上的锁,
这是很耗费资源的,无形中会降低程序的运行效率。
同步方法: 格式,在函数上加上synchronized修饰符即可。
8. 线程间通信
wait(),notify(),notifyAll(),用来操作线程定义在了Object类中的原因:
(1) 这些方法存在与同步中。
(2) 使用这些方法时必须要标识所属的同步的锁。
(3) 锁可以是任意对象,所以任意对象调用的方法一定定义Object类中。
(4) wait(),sleep()的区别:
wait(): 释放cpu执行权,释放锁。
sleep(): 释放cpu执行权,不释放锁。
9. 停止线程
定义循环结束标记,因为线程运行代码一般都是循环,只要控制了循环即可。
使用interrupt(中断)方法。该方法是结束线程的冻结状态,使线程回到运行状态中来。
注:stop方法已经过时不再使用。
10. 线程类的其他方法
currentThread():返回当前正在执行的线程对象
setPriority(int num): 更改线程的优先级。
setDaemon(boolean b): 将该线程标记为守护线程或用户线程。
join(): 等待该线程终止。
toString(): 返回该线程的字符串表示形式,包括线程名称、优先级和线程组。
11. 单例设计模式
保证类在内存中只有一个对象。饿汉式(开发用)与懒汉式(面试用)
实现原理:
(1) 让外界不能创建对象,私有化构造方法
(2) 自己创建一个对象,私有并静态化自己创建的对象
(3) 提供公共的访问方式,通过静态方法返回创建的静态成员对象.
单例设计的应用: 网站的计数器,windows的打印服务。
在JDK的源码中,有一个类也使用的是单例设计模式: Runtime
代码实例:
// 学生类的单例(饿汉式)
- <SPAN style="FONT-SIZE: 14px">package cn.lzz.single;
- public class Student {
- private Student(){}
- private static Student s = new Student();
- public static final Student getInstance(){
- return s;
- }
- private String name;
- private int Score;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getScore() {
- return Score;
- }
- public void setScore(int score) {
- Score = score;
- }
- public void display(){
- System.out.println("姓名: "+getName()+"\t成绩: "+getScore());
- }
- }
- </SPAN>
package cn.lzz.single;
public class Student {
private Student(){}
private static Student s = new Student();
public static final Student getInstance(){
return s;
}
private String name;
private int Score;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return Score;
}
public void setScore(int score) {
Score = score;
}
public void display(){
System.out.println("姓名: "+getName()+"\t成绩: "+getScore());
}
}
- <SPAN style="FONT-SIZE: 14px">// 老师类的单例(懒汉式)
- package cn.lzz.single;
- public class Teacher {
- private Teacher(){}
- private Teacher(String name){
- this.name = name;
- }
- private static Teacher t = null;
- public static synchronized Teacher getInstance(){
- if(t == null){
- t = new Teacher("LZZ");
- }
- return t;
- }
- private String name;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public void show(){
- System.out.println("姓名: "+getName());
- }
- }
- </SPAN>
// 老师类的单例(懒汉式)
package cn.lzz.single;
public class Teacher {
private Teacher(){}
private Teacher(String name){
this.name = name;
}
private static Teacher t = null;
public static synchronized Teacher getInstance(){
if(t == null){
t = new Teacher("LZZ");
}
return t;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("姓名: "+getName());
}
}
// 单例测试
- <SPAN style="FONT-SIZE: 14px">package cn.lzz.single;
- public class SingleTest {
- /**
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- // Student s = new Student();
- Student s = Student.getInstance();
- s.setName("张三");
- s.setScore(33);
- s.display();
- Teacher t1 = Teacher.getInstance();
- Teacher t2 = Teacher.getInstance();
- t1.show();
- t2.show();
- System.out.println("t1==t2: "+(t1==t2));
- }
- }
- </SPAN>
package cn.lzz.single;
public class SingleTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
// Student s = new Student();
Student s = Student.getInstance();
s.setName("张三");
s.setScore(33);
s.display();
Teacher t1 = Teacher.getInstance();
Teacher t2 = Teacher.getInstance();
t1.show();
t2.show();
System.out.println("t1==t2: "+(t1==t2));
}
}
单例测试结果
练习巩固
1. 线程示例(继承Thread类)
- <SPAN style="FONT-SIZE: 14px">package cn.lzz.thread;
- public class ThreadDemo extends Thread {
- private String name;
- ThreadDemo(String name){
- super(name);
- }
- @Override
- public void run() {
- for (int i = 0; i < 50; i++) {
- System.out.println(Thread.currentThread().getName()+"..."+i);
- }
- }
- }
- </SPAN>
package cn.lzz.thread;
public class ThreadDemo extends Thread {
private String name;
ThreadDemo(String name){
super(name);
}
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println(Thread.currentThread().getName()+"..."+i);
}
}
}
线程示例测试结果
2. 售票例子(实现Runnable接口)
- <SPAN style="FONT-SIZE: 14px">package cn.lzz.thread_app;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- //class Demo{}
- public class TicketDemo implements Runnable {
- // 定义100张票
- private int tickets = 100;
- // private Object obj = new Object();
- // Demo obj = new Demo();
- private Lock lock = new ReentrantLock();
- @Override
- public void run() {
- while (true) {
- // synchronized(obj){
- lock.lock();
- if (tickets > 0) {
- try {
- Thread.sleep(10);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + "正在出售第"
- + (tickets--) + "张票");
- }
- lock.unlock();
- // }
- }
- }
- }
- </SPAN>
package cn.lzz.thread_app;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//class Demo{}
public class TicketDemo implements Runnable {
// 定义100张票
private int tickets = 100;
// private Object obj = new Object();
// Demo obj = new Demo();
private Lock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
// synchronized(obj){
lock.lock();
if (tickets > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第"
+ (tickets--) + "张票");
}
lock.unlock();
// }
}
}
}
// 售票例子测试
- <SPAN style="FONT-SIZE: 14px">package cn.lzz.thread_app;
- public class TicketDemoTest {
- /**
- * @param args
- */
- public static void main(String[] args) {
- // 创建实现了Runnable接口的子类对象
- TicketDemo td = new TicketDemo();
- // 创建线程对象
- Thread t1 = new Thread(td, "窗口1");
- Thread t2 = new Thread(td, "窗口2");
- Thread t3 = new Thread(td, "窗口3");
- Thread t4 = new Thread(td, "窗口4");
- t1.start();
- t2.start();
- t3.start();
- t4.start();
- }
- }
- </SPAN>
package cn.lzz.thread_app;
public class TicketDemoTest {
/**
* @param args
*/
public static void main(String[] args) {
// 创建实现了Runnable接口的子类对象
TicketDemo td = new TicketDemo();
// 创建线程对象
Thread t1 = new Thread(td, "窗口1");
Thread t2 = new Thread(td, "窗口2");
Thread t3 = new Thread(td, "窗口3");
Thread t4 = new Thread(td, "窗口4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
售票例子运行结果
3. 死锁示例
- package cn.lzz.thread;
- class Test implements Runnable{
- private boolean flag;
- Test(boolean flag){
- this.flag = flag;
- }
- public void run(){
- if(flag){
- synchronized(MyLock.locka){
- System.out.println(Thread.currentThread().getName()+"...if...locka...");
- synchronized(MyLock.lockb){
- System.out.println(Thread.currentThread().getName()+"...if...lockb...");
- }
- }
- }else{
- synchronized(MyLock.lockb){
- System.out.println(Thread.currentThread().getName()+"...else...lockb...");
- synchronized(MyLock.locka){
- System.out.println(Thread.currentThread().getName()+"...else...locka...");
- }
- }
- }
- }
- }
- class MyLock{
- public static final Object locka = new Object();
- public static final Object lockb = new Object();
- }
- public class DeadLockTest {
- /**
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- Test a = new Test(true);
- Test b = new Test(false);
- Thread t1 = new Thread(a);
- Thread t2 = new Thread(b);
- t1.start();
- t2.start();
- }
- }
package cn.lzz.thread;
class Test implements Runnable{
private boolean flag;
Test(boolean flag){
this.flag = flag;
}
public void run(){
if(flag){
synchronized(MyLock.locka){
System.out.println(Thread.currentThread().getName()+"...if...locka...");
synchronized(MyLock.lockb){
System.out.println(Thread.currentThread().getName()+"...if...lockb...");
}
}
}else{
synchronized(MyLock.lockb){
System.out.println(Thread.currentThread().getName()+"...else...lockb...");
synchronized(MyLock.locka){
System.out.println(Thread.currentThread().getName()+"...else...locka...");
}
}
}
}
}
class MyLock{
public static final Object locka = new Object();
public static final Object lockb = new Object();
}
public class DeadLockTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Test a = new Test(true);
Test b = new Test(false);
Thread t1 = new Thread(a);
Thread t2 = new Thread(b);
t1.start();
t2.start();
}
}
死锁示例运行结果
-------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------