1.一个进程可以包含多个线程,它们共享进程资源
2.JAVA中,实现多线程有两种方法: 继承Thread类,实现Runnable接口,由于JAVA不支持多继承,因此要根据实际问题选择实现方法。
(1)Thread类
从Thread类派生一个子类,并创建这个子类的对象,就可以产生一个新的线程;
这个子类应该重写Thread类的run方法,在run方法中写入需要在新线程中执行的语句段。这个子类的对象需要调用start方法来启动,新线程将自动进入run方法。原程序将同时继续往下执行;
Thread类直接继承了Object类,并实现了Runnable接口。
hread类位于java.lang包中,因而程序开头不用import任何包就可直接使用。
练习
创建2个线程,一个线程负责输出英文字母表,另一个线程负责输出希腊字母表。
通过继承Thread类实现创建线程。
(2)Runnable接口
只有一个run()方法
实现Runnable接口的类的对象可以用来创建线程,这时start方法启动此线程就会在此线程上运行run()方法
通常使用Thread(Runnable target)构造方法创建线程
class Kitty implements Runnable{ public void run() { for (int i = 1; i <= 50000; i++) if(i % 10000 == 0) System.out.println("小喵猫猫叫~"); } }
public class Main
{
public static void main(String[] args)
{
Kitty k = new Kitty();
Thread kitty =new Thread(k);
kitty.start();
for (int i = 1; i <= 50000; i++)
{
if(i % 10000 == 0)
System.out.println(
"主人嗷嗷喊~~~");
}
}
}
(3)线程的生命周期
线程的生命周期是指线程从产生到消亡的过程,一个线程在任何时刻都处于某种线程状态(thread state)
class ClassRoom implements Runnable { Thread student,teacher; ClassRoom() { teacher=new Thread(this); student=new Thread(this); teacher.setName("李老师"); student.setName("张三"); } public void run(){ if(Thread.currentThread()==student) { try{ System.out.println(student.getName()+"正在睡觉,不听课"); Thread.sleep(1000*60*45); } catch(InterruptedException e) { System.out.println(student.getName()+"被老师叫醒了"); } System.out.println(student.getName()+"开始听课"); } else if(Thread.currentThread()==teacher) { for(int i=1;i<=3;i++) { System.out.println("上课!"); try{ Thread.sleep(1000); } catch(InterruptedException e){ } } student.interrupt(); //吵醒student } } } public class Main { public static void main(String[] args) { ClassRoom room317=new ClassRoom(); room317.student.start(); room317.teacher.start(); } }
协调同步线程
wait()方法可以中断方法的执行,使本线程等待,暂时让出CPU的使用权,并允许其它线程使用这个同步方法。
notifyAll()方法通知所有的由于使用这个同步方法而处于等待的线程结束等待。曾中断的线程就会从刚才的中断处继续执行这个同步方法,并遵循“先中断先继续”的原则。
notify()方法只是通知处于等待中的线程的某一个结束等待。
练习
每学期开学,教材科需要购入和出售教材。创建2个线程,一个线程负责购入教材,另一个线程负责向学生出售教材。两个线程都要操作教材科的教材种类及册数数据。
要求通过线程同步,保证一个线程操作完之后,另一个线程再执行。