本系列学习笔记简介
传智播客的毕向东Java基础教程是免费公开的一份面向初学者的Java学习教程。在我学习毕老师的Java基础教程过程中,苦于其并没有附带练习题,总觉得学的‘轻飘飘’的,所以决定每天看完的一些内容,总在接下来的几天里找一些时间写下来,看看自己还记得多少,看看自己哪些知识点理解的不透彻。希望本系列学习笔记在帮助自己理清思路,理顺知识点的同时,也能够帮助其他在学习Java的同学。欢迎大家在评论区讨论相关内容。
多线程的继承Thread类实现
进程线程简介
进程可以认为是一个正在运行中的程序,你打开任务管理器就可以看到进程。而线程是这个进程中,为了完成一些任务而相互独立进行的代码集合,比如你在360安全卫士中打开安全检查的同时又可以清扫垃圾,这时你就开启了两个线程。
多线程卖票介绍
我们这里通过一个卖票例子来讲解多线程的继承Thread类实现。我们假设共有100张编号为1到100的票,在命令行打印一个数字就视为卖出了对应编号的票,我们首先采用继承Thread类来实现。
思路:创建一个类来继承Thread类,在子类中重写run()方法来覆盖父类Thread中的run()方法。
代码块
错误代码块
class Ticket extends Thread
{
private int num = 100;
public void run()
{
while(true)
{
if(num>0)
System.out.println(Thread.currentThread().getName()+"....."+"num="+num--);
}
}
}
class TicketDemo
{
public static void main(String[] args)
{
Ticket t1 = new Ticket();
Ticket t2 = new Ticket();
t1.start();
t2.start();
}
}
上述代码的部分运行结果为:
我们看到线程0与线程1卖出了同样的票号,这是我们不希望看到的,这100号座位旅客0坐还是旅客1坐合适啊?究其原因,是因为我们new了两个Ticket对象,每生成一个Ticket对象,JVM虚拟机的堆内存中都会有属于该对象的成员变量num=100,所以num- -的时候每个票号都会出现两次。我们可以选择把num变为静态变量,这样它就会被JVM存储在方法区中,被Ticket对象所共享。
正确代码块
class Ticket extends Thread
{
private static int num = 100;//我们只是在这里加上了static关键字
public void run()
{
while(true)
{
if(num>0)
System.out.println(Thread.currentThread().getName()+"....."+"num="+num--);
}
}
}
class TicketDemo
{
public static void main(String[] args)
{
Ticket t1 = new Ticket();
Ticket t2 = new Ticket();
t1.start();
t2.start();
}
}
注意:这个所谓的正确代码块,还是存在安全隐患的,因为如果线程0执行到num=1到了判断语句之后,这时如果线程1进来,那么会输出Thread=1…num=1,随后切换到线程0,输出就会为Thread=0…num=0
通过接口Runnable实现多线程
由于Java不允许多继承,所以当一个类已经有父类时就不能够继承Thread类了,这时要通过接口Runnable实现多线程。使用实现接口Runnable的对象创建线程,当启动线程时,在独立运行的线程中就会调用对象的run方法。
代码块
class ThreadDemo
{
public static void main(String[] args)
{
Ticket t = new Ticket();
// 使用实现Runnable接口的对象创建一个线程
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
//启动该线程,将导致在独立运行的线程中调用该对象的run方法
t1.start();
t2.start();
}
}
class Ticket implements Runnable
{
public int num=100;
public void run()
{
while(true)
{
if(num>0)
System.out.println(Thread.currentThread().getName()+"..."+num--);
}
}
}
命令行运行结果为
最后要注意的几点:
1.上述实现多线程是不安全的,还需要通过同步关键字synchronized来保证安全。
2.实现多线程常见的有三种方式,这里介绍了通过继承Thread类实现,通过实现接口Runnable实现,最后一种我们有机会再说。