多线程知识点小结

来源:互联网 发布:ico透明图标制作软件 编辑:程序博客网 时间:2024/04/30 14:25

                            黑马程序员     

多线程知识点小结

------- android培训java培训、期待与您交流!----------

(一)知识点框架

1:多线程(理解)
(1)如果一个应用程序有多条执行路径,则被称为多线程程序。
进程:正在执行的程序。
线程:程序的执行路径,执行单元。
单线程:如果一个应用程序只有一条执行路径,则被称为单线程程序。
多线程:如果一个应用程序有多条执行路径,则被称为多线程程序。

举例:迅雷下载,360的管理界面。

多线程:多个人吃统一盘菜

(2)多线程程序实现的两种方案:(掌握 步骤我们一起写,代码你写)
A:继承Thread类
a:自定义类MyThread继承Thread类。
b:重写run方法(),在这里面输出1-100的数据。
c:定义测试类MyThreadTest,在测试类中创建MyThread类的多个对象。
d:调用start()

代码体现:
public class MyThread extends Thread {

public MyThread(){}

public MyThread(String name) {
super(name);
}

public void run() {
for(int x=1; x<=100; x++) {
System.out.println(getName()+"---"+x);
}
}
}

public class MyThreadTest {
public static void main(String[] args) {
MyThread my1 = new MyThread("三国志");
MyThread my2 = new MyThread("三国杀");


//my1.setName("三国志");
//my2.setName("三国杀");


my1.start();
my2.start();
}
}

B:实现Runnable接口
a:自定义类MyRunnable实现Runnable接口。
b:重写run方法(),在这里面输出1-100的数据。
c:定义测试类MyThreadTest,在测试类中创建MyRunnable类的一个对象。
d:在测试类创建Thread类的多个对象,并把MyRunnable类的一个对象作为构造参数传递。
e:调用start()


代码体现:
public class MyRunnable implements Runnable {
public void run() {
for(int x=1; x<=100; x++) {
System.out.println(Thread.currentThread().getName()+"---"+x);
}
}
}

public class MyRunnableTest {
public static void main(String[] args) {
MyRunnable my = new MyRunnable();


Thread t1 = new Thread(my,"斗地主");
Thread t2 = new Thread(my,"三国群英传2");

t1.start();
t2.start();
}
}

(3)面试题:
A:如何启动一个线程
B:start()和run()方法的区别
C:线程随机性原理
D:线程的生命周期
E:线程的安全问题是怎么产生的,以及是如何解决的?
F:同步解决线程安全问题的方式有几种?
G:同步代码块的锁对象是谁?同步方法的锁对象是谁?
F:静态方法的锁对象是谁?
(4)几个方法
优先级(priority)
暂停(yield)
加入(join)
守护线程
线程睡眠(sleep)
线程中断(interrupt)
(5)案例:
卖票案例。


线程安全问题:
怎么产生的:
A:多线程环境
B:有共享数据
C:多条语句操作共享数据

怎么解决:
把C步骤给锁起来。

两种方案:
a:同步代码块
synchronized(锁对象) {
一个原子性操作
}
b:同步方法
把synchronized添加到方法声明上。返回值前。

(二)相关代码实现

继承Thread的两种实现方式

package cn.itcast;
/*
 * Thread:线程 是程序中的执行线程
 * 
 * 多线程的实现方法:
 * 方式一:继承Thread类
 * 自定义线程类继承Thread类。
 * 重写run方法。run方法内为该线程执行代码。将其理解为其他线程的main方法,即该线程的执行入口。
 * 使用:
 * 创建线程对象
 * 开启线程,即调用start方法,该方法会自动调用这个线程的run方法。
 */
public class Demo01_Thread {

public static void main(String[] args) {

MyThread mt = new MyThread();
MyThread mt2 = new MyThread();
MyThread mt3 = new MyThread();

// 直接调用线程对象的run方法,相当于没有线程,就是一个普通对象的普通方法
// mt.run();
// mt2.run();
// mt3.run();

Thread mainThread = Thread.currentThread();
mt.start();
mt2.start();
mt3.start();

for (int i = 0; i < 100; i++) {
System.out.println(mainThread.getName()+"我是一个线程,我执行了!");
}
}
}


package cn.itcast;
/*
 * Runnable:线程执行目标接口  
 * 该接口当中有一个run方法,这个run方法内完成业务逻辑。
 * 如果哪个线程想执行对应的业务逻辑,就使用哪个线程执行目标对象。
 * 使用Runnable的子类对象去创建线程,则该线程就执行这个Runnable子类对象的run方法内容
 * 



 * 多线程的实现方法:
 * 方式二:实现Runnable接口
 * 自定义Runnable 的子类(非线程类)。
 * 重写run方法。run方法内为该类对象所在线程的执行代码。同样可将其理解为其他线程的main方法,即该线程的执行入口。
 * 使用:
 * 创建Runnable的子类对象。
 * 使用Runnable的子类对象创建线程对象。
 * 开启线程,即调用start方法,该方法会自动调用这个线程的run方法。
 */
public class Demo02_Thread {

public static void main(String[] args) {
//创建线程执行目标类对象
MyRunnable mr = new MyRunnable();

//使用线程执行目标类对象创建线程
Thread thread = new Thread(mr,"安萍的线程");
Thread thread2 = new Thread(mr,"小涔的线程");
Thread thread3 = new Thread(mr,"小蔡的线程");

//开启线程
thread.start();
thread2.start();
thread3.start();
}
}

package cn.itcast;


/*
 * 定义一个线程执行目标类实现Runnable接口
 */
public class MyRunnable implements Runnable {


/*
* 实现run方法,完成业务逻辑
* 该方法会被使用MyRunnable对象的线程所调用
*/

@Override
public void run() {
//让该线程执行100遍相同代码
for (int i = 0; i < 100; i++) {
//获取当前所执行的线程对象
Thread currentThread = Thread.currentThread();
//打印信息
System.out.println(currentThread.getName()+"我是一个线程,我执行了!"+i);
}
}
}


售票案例

package cn.itcast4;
/*
 * 同步方法:
 * 在方法上加同步
 * 
 * 声明同步方法:在返回值前加synchronized修饰
 * 同步方法的锁为所在对象:this
 */
public class Demo01_Thread {
public static void main(String[] args) {
//创建线程执行目标类对象
Tickets tickets = new Tickets();

//使用线程执行目标类对象创建线程对象
Thread t = new Thread(tickets,"粪粪");
Thread t2 = new Thread(tickets,"念念");
Thread t3 = new Thread(tickets,"青青");

//开启线程
t.start();
t2.start();
t3.start();
}
}



package cn.itcast4;
/*
 * 定义线程执行目标类
 */
public class Tickets implements Runnable{


//定义成员变量number用来记录票数,供多个线程共享使用
static int number = 100;
//定义一个变量,记录奇偶状态
int x = 0;
//定义卖票逻辑
public void run() {
while(true) {
if(x%2==0) {
//使用同步代码块,将需要同步的代码包裹
// 非静态方法的锁为对象this
synchronized (this) {
// 静态方法的锁为其所在类类本身
// synchronized (Tickets.class) {
//如果票数是正的,说明有票,就卖票
if(number>0) {
//每卖一张票就将票数减1
System.out.println(Thread.currentThread().getName()+"正在销售第"+ number +"号票");
number--;
}
}
}else {
method();
}
x++;
}
}
// //同步方法:在方法上加同步
// public synchronized void method() {
// //使用同步代码块,将需要同步的代码包裹
// try {
// Thread.sleep(10);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
//
// //如果票数是正的,说明有票,就卖票
// if(number>0) {
// //每卖一张票就将票数减1
// System.out.println(Thread.currentThread().getName()+"正在销售第"+ number +"号票");
// number--;
// }
// }

public static synchronized void method() {
//使用同步代码块,将需要同步的代码包裹
// synchronized (lock) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}

//如果票数是正的,说明有票,就卖票
if(number>0) {
//每卖一张票就将票数减1
System.out.println(Thread.currentThread().getName()+"正在销售第"+ number +"号票");
number--;
}
// }
}


}

0 0