进程:正在运行的程序。(即程序在内存中开辟了一片空间)
线程:是进程的执行单元。
一个进程至少包含了一个多个线程。
多线程是不是可以提高效率:多线程可以合理的利用系统的资源,提高效率是相对的。因为cpu时间片的切换,可以在极短的时间内处理多个线程的任务。
也就是说开启线程后并不是立即调用run方法,cpu在切换,切到了该线程,就调用run方法。
创建多线程的方法一:
通过集成Thread,并复写run方法。
packagethread;importorg.junit.Test;class Demo extendsThread{privateString username;publicString getUsername() {returnusername;
}public voidsetUsername(String username) {this.username =username;
}publicDemo(String username) {super();this.username =username;
}publicDemo() {super();
}//复写run方法
public voidrun(){for (int i = 1; i <= 10; i++) {
System.out.println(Thread.currentThread().getName()+"......"+i);
}
}
}public classThreadDemo {
@Testpublic voidtest1(){/** 创建线程的第一种方式:
* 1、继承Thread类。 2、覆盖run方法。 3、创建子类对象就是创建线程。
* 4、调用Thread类中的start方法就是在开启线程,并执行run方法*/Demo d1= new Demo("张三");
Demo d2= new Demo("李四");//d1.run();//d2.run();//开启线程
d1.start();//start():两件事:1、开启线程。 2、调用run方法
d2.start();/** start和run的区别:
* 调用start会开启线程,让开启的线程去执行run方法中的线程任务。
* 直接调用run方法,线程并没有开启,去执行run方法的只有主线程(即当前线程)。
*
* start()开启线程后,都会执行run方法,说明run方法中存储的都是线程要
* 运行的代码。所以记住,自定义线程的任务代码都要存储在run方法中。*/
for (int i = 1; i <= 10; i++) {
System.out.println(Thread.currentThread().getName()+"...."+i);
}
}
}
运行结果:
创建线程的第二种方式:
packagethread;/** 创建线程的第二种方式:
* 1、定义一个类型实现Runable接口。
* 2、覆盖Runable接口中的run方法,将要运行的任务代码定义到run方法中。
* 3、通过Thread类创建线程,同时将 实现了Runable接口的对象作为Thread类的构造函数的参数传入。
* 4、Thread类对象调用start方法开启线程。*/
class SaleTicket implementsRunnable{private int tickets = 100;//卖票的代码需要被多个线程执行,所以要讲这些代码定义在线程中。run方法
public voidrun(){while (tickets > 0) {
System.out.println(Thread.currentThread().getName()+"....."+tickets--);
}
}
}public classTicketDemo {public static voidmain(String[] args) {//创建实现了runable接口的对象,线程任务对象
SaleTicket st = newSaleTicket();//创建四个线程,实现runable接口后创建对象通过Thread类
Thread t1 = newThread(st);
Thread t2= newThread(st);
Thread t3= newThread(st);
Thread t4= newThread(st);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
运行结果:
实现Runable接口的好处:
1、避免了继承Thread类的单继承局限性。
2、Runable接口出现更符合面向对象,将线程单独进行对象的封装。
3、Runable接口出现,降低了线程对象和线程任务的耦合性。
所以,以后创建线程都用第二种方式。