第一章:进程和线程:
1.进程的介绍:
是一个程序运行状态和资源占用(内存,Cpu)的描述,进程是程序的一个动态过程,值的是从代码加载到执行完毕的一个完整过程
进程的特点:
1.独立性,不同的进程之间是相互独立的,相互之间资源不共享
2.动态性:进程在系统中不是静止不动的,而是在系统中一直活动
3.并发性:多个进程可以在单个处理器上同时进行,且互不影响
2.线程的介绍:
线程是进程的一部分,一个进程可以有多个线程,每个线程区处理一个特定的子任务
线程的执行时抢占式的,多个线程在同一个进程中可以并发执行,其实就是cpu快速的在不同的线程之间切换,也就是说,当前运行的线程在任何时候都有可能被挂起,以便另外一个线程可以运行
第二章:多线程的实现
1.继承Thread类
继承Thread类创建并启动多线程的步骤:
a.定义一个类,继承自Thread类,并重写该类的run方法,该run方法的方法体就代表了线程需要完成的任务,因此,run方法的方法体被称为线程执行体
b.创建Thread子类的对象,即创建了子线程
c.用线程对象的Start方法来启动该线程
代码实现:
public class ThreadUsageDemo1{
public static void main(String[] args){
//实际的子线程
MyThread t0=new MyThread();
t0.setName("线程0000");
t0.start();
MyThread1 t1=new MyThread1();
t1.setName("线程1111");
t1.start();
/*
* static Thread currentThread()
返回对当前正在执行的线程对象的引用
*
*/
//这个方法调用在哪个线程的线程执行体中,则指的是哪个当前正在执行的线程
Thread thread=Thread.currentThread();
System.out.println(thread); //Thread[main,5,mian]
// Thread[Thread-0,5,main]
// Thread[Thread-1,5,main]
//Thread[线程的名字,线程的执行优先级,在哪个线程中创建的]
System.out.println(threa.getName());
//通过构造方法设置线程的名字
MyThread1 t2=new MyThread1("新的线程-------");
t2.start();
}
}
//线程类1
class MyThread extends Thread{
@Override
public void run(){
for(int i=0;i<10;i++){
System.out.println("hello"+i);
}
Thread thread =Thread.currentThread();
System.out.println(thread);
System.out.println(thread.getName());
}
}
//线程类2
class MyThread1 extends Thread{
public MyThread1(){}
public MyThread1(String name){
super(name); //调用了父类中的Thread(String name)
}
@Override
public void run(){
Thread thread =Thread.currentThread();
System.out.println(thread.getName());
}
}
案例:模拟售票员售票
public class ThreadTestDemo1{
public static void main(String[] args){
//需求:模拟4个售票员售100张票
SellTickets s1=new SellTickets();
SellTickets s2=new SellTickets();
SellTickets s3=new SellTickets();
SellTickets s4=new SellTickets();
s1.start();
s2.start();
s3.start();
s4.start();
}
}
public class SellTickets extends Thread{
//共享数据
static int count=100;
@Override
public void run(){
//循环售票
while(count>0){
count--;
System.out.println(Thread.currentThread().getName()+"售出了一张票,剩余"+count);
}
}
}
2.实现Runnable接口
实现Runnable接口创建并启动多线程的步骤:
a.定义一个Runnabel接口的实现类,并重写该接口中的run方法,该run方法的方法体同样是该线程的线程执行体
b.创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象
c.调用线程对象的start方法来启动该线程
public class ThreadUsageDemo2{
public static void main(String[] args){
//并不是线程对象
Check c=new Check();
/**
* Thread(Runnable target)
* 分配新的Thread对象
/
Thread t0=new Thread(c);
t0.start();
Thread t1=new Thread(c);
t1.start();
}
}
// 实现类
class Check implements Runnable{
@Override
public void run(){
for(int i=0;i<10;i++){
System.out.println(i);
}
}
}
案例:模拟售票员售票
public class ThreadTestDemo2{
static int count =100;
static Runnable r=new Runnable(){
@Overide
public void run(){
while(count>0){
count--;
System.out.println(Thread.currentThread().getName()+"售出了一张票,剩余"+count);
}
}
}
public static void main(String[] args){
Thread t0=new Thread(r);
Thread t1=new Thread(r);
Thread t2=new Thread(r);
Thread t3=new Thread(r);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
3.两种实现方法的比较:
实现Runnable接口的方式:
a.线程类只是实现Runnable接口,还可以继承其他类(一个类在实现接口的同时还可以继承另外一个类)
b.可以多个线程共享一个target对象,所以非常适合多个线程了来处理同一份资源的情况
c.弊端:编程稍微复杂,不直观,如果要访问当前线程,必须使用Thread.currentThread()
继承Thread类的方式
a.编写简单,如果要访问当前线程,除了可以通过Thread.currentThread()方式外,还可以使用supre关键字
b.弊端:因为线程类已经继承了Thread类,则不能再继承其他类(单继承)
实际上大多数的多线程应用都可以采用实现Runnable接口的方式来实现【推荐使用匿名内部类】
4.调用 start()与run()方法的区别
当调用start()方法时将创建新的线程,并且执行run()方法里的代码,但是如果直接调用start()方法,不会创建新的线程也不会执行调用线程的代码