如何创建一个控制单元或线程?
第一种方式:
1、继承Thread类。覆盖run方法,将多线程要运行的代码放到run方法中。
2、调用start方法,开启线程,并执行run方法。
※特性:随机性(每次执行的结果不一样,多个线程抢资源的结果)
※创建一个Thread类或其子类,才能够产生一个控制单元.
第二种方式:
1、实现Runnable接口,覆盖run方法.
2、调用Thread类建立线程对象,并将实现Runnable接口的子类对象作为参数传递给Thread的构造函数.
3、调用Thread类对象的start方法,开启并运行run方法.
为什么要将Runnable接口的子类对象作为参数传递给Thread类的构造方法呢?为了让多线程去执行自定义的run方法,该
run方法有自己所属的对象,所以将该对象传入.
线程的安全问题,产生的原因:
1、多个线程访问出现延迟;
2、线程的随机性;
同步:
1、解决线程的安全问题,同时会消耗资源,降低效率(每个线程都需要去判断同步上的锁). 例子:火车上的卫生间(锁);
2、需要同步的两个前提:①至少两个以上的线程;②多线程使用的是同一把锁;
3、注意同步的死锁,尽量避免同步嵌套的情况.
4、同步的两种表现形式:
①同步代码块,传递一个对象作为锁.
②同步函数,使用this作为锁。使用同步函数时,一定要注意分析哪些需要同步,在Tickets中,如将synchronized放到run方法上,
那么线程进入while无限循环,无法退出,锁无法被其他线程使用.所以,while循环不需要同步,而其中的内容才是需要同步的内容.
注意:1、线程在同步时,还是出现了安全隐患,结果很大程序出现在线程同步问题上,检查是否多线程使用的同一把锁.
2、静态方法的同步函数,锁肯定不是this,因为静态方法不能使用this,这是,锁为方法所在的类的class对象,例如,Tickets.class.
class MyThread extends Thread
{
private String name;
MyThread(String name)
{
this.name = name;
}
public void run() //覆盖run方法
{
for (int x = 0; x < 10 ; x++)
{
System.out.println(Thread.currentThread().getName() + "..name:" + name + "-" + x);
}
}
}
//铁路售票例子,四个窗口同时售票
class Tickets implements Runnable
{
private static int ticketsCnt = 100; //总共100张票
Object obj = new Object();
boolean b = true;
public void run()
{
//for (int x = ticketsCnt; x > 0; x--) //为什么for循环这样写不行呢?
if (b)
{
while (true)
{
show();
}
}
else
{
while (true)
{
synchronized(Tickets.class) //(this) //obj
{
if (ticketsCnt > 0)
{
try
{
Thread.sleep(10); //模拟线程的安全问题。
}
catch (Exception e)
{
//
}
System.out.println(Thread.currentThread().getName() + " ->code.... " +ticketsCnt--);
}
}
}
}
}
public synchronized static void show() //同步函数,添加关键字synchronized,锁为this,如果声明为static,则锁为Tickets.class
{
if (ticketsCnt > 0)
{
try
{
Thread.sleep(10); //模拟线程的安全问题。
}
catch (Exception e)
{
//
}
System.out.println(Thread.currentThread().getName() + " ->func.... " +ticketsCnt--);
}
}
}
class ThreadDemo
{
public static void main(String[] args) // 当前程序有三个线程,包括主线程!
{
//MyThread d1 = new MyThread("one"); //线程1
//MyThread d2 = new MyThread("two -");//线程2
//d1.start();
//d2.start();
//主线程
//for (int n = 0; n < 10; n++)
//{
// System.out.println(Thread.currentThread().getName() + ".." + n);
//}
Tickets t = new Tickets();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
//Thread t3 = new Thread(t);
//Thread t4 = new Thread(t);
t1.start();
try
{
Thread.sleep(10); //让主线程停下来,不让程序首先执行 t.b = false;
}
catch (Exception e)
{
//
}
t.b = false;
t2.start();
//t3.start();
//t4.start();
}
}