一、 进程与线程
1 进程:每个独立运行着的程序称为一个进程
2 线程:线程是一个进程内部的一条执行路径,java虚拟机允许应用程序并发地运行多个执行,
使系统独立调度和分派cpu的基本位
3 多线程:多线程就是在一个进程中创建多个线程,每个线程完成一个任务
优点:多线程技术使程序响应速度更快
提高资源利用率
程序设计更简单
4 进程、线程区别
进程有独立的地址空间,一个进程崩溃后,不会对其他进程产生影响,而线程只是一个进程中的不同执行路径
线程有自己的栈和局部变量,多个线程共享同一进程的地址空间
一个进程至少有一个线程
5 线程的五中状态
6 ava中创建多线程的两种方式
一:继承Thread类
二:实现Runnable接口
7 比较两种创建线程的方法
1>继承Thread
适合每个线程是独立执行,没有资源共享
例如
package com.qf.day21_1;
/**
*
* 卖票,每个窗口各卖100张票
* @author Administrator
*
*/
public class Demo3 {
public static void main(String[] args) {
winTic w1 = new winTic("窗口1");
winTic w2 = new winTic("窗口2");
winTic w3 = new winTic("窗口3");
winTic w4 = new winTic("窗口4");
w1.start();
w2.start();
w3.start();
w4.start();
}
}
class winTic extends Thread{
private int ticket = 100;
public winTic(String name) {
super(name);
}
@Override
public void run() {
while(true){
if(ticket<=0){
break;
}
System.out.println(Thread.currentThread().getName()+"卖第"+(ticket--)+"张票");
}
}
}
2>实现Runnable
适合存在资源共享的情况,要和Thread类结合使用
资源共享分两种情况
(1)相同操作,同一个资源
操作代码和资源同一个类中,并实现Runnable接口
例如
/**
* 卖票
* 需求:四个窗口共卖100张票
* @author Administrator
*
*/
public class Demo4 {
public static void main(String[] args) {
TicketRes res = new TicketRes();
Thread w1 = new Thread(res,"窗口1");
Thread w2 = new Thread(res,"窗口2");
Thread w3 = new Thread(res,"窗口3");
Thread w4 = new Thread(res,"窗口4");
w1.start();
w2.start();
w3.start();
w4.start();
}
}
/**
*
* 票类
* @author Administrator
*
*/
class TicketRes implements Runnable{
private int tickets = 100;
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
if (tickets<=0) {
break;
}
System.out.println(Thread.currentThread().getName()+"卖票"+tickets--);
}
}
}
(2)不同操作,同一个资源
资源单独一个类,操作分别在不同类中,并实现Runnable接口
例如
/**
* 有一张银行卡余额为0;一人存,一人取
* @author Administrator
*
*/
public class demo5 {
public static void main(String[] args) {
BankCard card = new BankCard();
addMoney add =new addMoney(card);
subMoney sub = new subMoney(card);
Thread zhangsan = new Thread(add,"张三");
Thread lisi = new Thread(sub,"李四");
zhangsan.start();
lisi.start();
}
}
/**
* 银行卡
*
*/
class BankCard{
double money;
}
/**
* 存钱
* @author Administrator
*
*/
class addMoney implements Runnable{
private BankCard card;
public addMoney(BankCard card) {
// TODO Auto-generated constructor stub
this.card = card;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++) {
this.card.money +=1000;
System.out.println(Thread.currentThread().getName()+"存了100元,卡内余额"+this.card.money);
}
}
}
/**
* 取钱
* @author Administrator
*
*/
class subMoney implements Runnable{
private BankCard card;
public subMoney(BankCard card) {
this.card = card;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++) {
if (this.card.money>=1000) {
this.card.money-=1000;
System.out.println(Thread.currentThread().getName()+"取了1000元,卡内余额"+this.card.money);
}else {
System.out.println("卡内余额不足");
i--;
}
}
}
}
7 线程调度
•多个线程处于可运行状态
◦分配优先级:反映线程的重要或紧急程度
–◦线程的优先级用1~10 表示,1的优先级最低,10的优先级最高,默认值是5
◦更改优先级用setPriority(int grade)方法
8 线程调度的方法
◦
join()方法
使用join()方法调度线程
package com.qf.day21_2;
public class Demo1 {
public static void main(String[] args) throws Exception {
joinThread j1 = new joinThread("线程一");
joinThread j2 = new joinThread("线程二");
j1.start();
j2.start();
j1.join();//阻塞主线程等到j1执行完,才能继续执行
for (int i = 0; i < 50; i++) {
System.out.println("主线程"+i);
}
}
}
class joinThread extends Thread{
String name ;
public joinThread(String name) {
// TODO Auto-generated constructor stub
super(name);
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 50; i++) {
System.out.println(Thread.currentThread().getName()+i+"--------");
}
}
}
◦
sleep()方法
•使用sleep()方法调度线程
◦public static voidsleep(long millis);
◦当前线程在指定毫秒内停止执行而转入不可运行状态
public void run() {
for (int i = 0; i < 5; i++) {
……
}
try {
Thread.sleep(10000);//等待10秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
◦
yield()方法
•
使用yield()方法调度线程
让给其它线程执行
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+" "+i );
yield();//暂停回到可执行状态
}
}
9 线程的终止
1 >正常终止 , 通过标志位控制
1 >正常终止 , 通过标志位控制
◦使用标志,使run()方法正常执行完
2>
◦使用stop方法强行终止线程
– 这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果
3 >通过interrupt()方法来终止线程
只能中断正在阻塞的线程,或在调用interrupt方法之后,子线程执行了能抛出InterruptedException异常的方法,比如sleep(),wait(),join()等方法
2 >stop();