程序:安装在磁盘上的一段指令集合,它是静态的概念
进程:运行中的程序,是动态的概念,每个进程有独立的资源空间。
线程:又称为轻量级进程,是程序执行的最小单元,是程序中的一个单一的顺序流程,
线程是进程中的一个实体,是被系统独立调度和分派的基本单位。
多线程:指在单个程序中可以同时运行不同的线程,执行不同的任务。
创建线程:
一 1、Java类如继承Thread类,就成为一个线程类,并可通过该类start方法来启动线程,
执行代码。
2、Thread类的子类可以直接实例化,但在子类中必须覆盖run方法才能真正运行线程的代码。
二、通过实现Runnable接口创建线程。
实现Runnable接口的类必须借助Thread类才能创建线程,
eg:1、创建实现Runnable接口的实例
2 、创建一个Thread的对象。将第一个实例化得到的Runnable对象作为参数传到
Thread类的构造方法中。
通过start方法启动线程。
线程的生命周期:
新建 、就绪 、运行、阻塞、 死亡 五种不同的状态可以通过Thread类的方法控制。
1、新建:new操作后,创建了一个线程,该线程仅仅是一个空对象,没有分配资源,
2、就绪:使用start方法后,系统就给线程分配除CPU外的资源,如果某个线程执行了yield方法
则该线程被剥夺了CPU资源,进入就绪状态。
3、运行:占有CPU方法,系统真正执行run()方法。
4、阻塞:因原因不能继续执行时, 原因:对象执行sleep方法等方法时。wait方法时等,
5、死亡: 执行interrupt和stop方法,形成进入死亡状态、。
run方法执行完,则自动死亡。
多线程编程::
线程同步:为了防止多个线程访问一个数据对象时,对数据造成破坏
保证多线程安全访问竞争资源的一种手段。
就是给线程加个限制,让线程执行时别的线程不能执行相应代码。
同步和锁:
Java中每个对象都有一个内置锁。
线程同步一般:把竞争资源设置为private
同步那些访问资源的代码,使用synchronized关键字来修饰方法或代码块,当
synchronized 方法执行完或放生异常时,会自动解锁。、
eg:用synchronized方法设置同步线程。
public class BankDemo{
public static void main(String [] args){
Bank bank= new Bank();
BankThread b1= new BankThread(bank);
b1.start();
BankThread b2= new BankThread(bank);
b2.start();
}
}
class BankThread extends Thread{
private Bank bank =null;
public BankThread(Bank bank){
this.bank =bank;
}
public void run(){
System. out.println("余钱:" +bank .getMoney(400));
}
}
class Bank{
private int money =500;
//取钱方法:
//当一个线程去调用同步方法时,这个线程就获得了当前对象的锁。
//其他线程调用同步方法时只能等待。
public synchronized int getMoney(int number){
if(number<0){
return -1;
} else if (money <0){
return -2;
} else if (number-money >0){
return -3;
} else{
try {
Thread. sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
money-=number;
System. out.println(“取钱:” +number);
}
return money ;
}
}
eg:同步代码块 :就是把synchronized方法 包住要执行的代码:
public class BankDemo{
public static void main(String [] args){
Bank bank= new Bank();
BankThread b1= new BankThread(bank);
b1.start();
BankThread b2= new BankThread(bank);
b2.start();
}
}
class BankThread extends Thread{
private Bank bank =null;
public BankThread(Bank bank){
this.bank =bank;
}
public void run(){
System. out.println("余钱:" +bank .getMoney(400));
}
}
class Bank{
private int money =500;
//取钱方法:
//当一个线程去调用同步方法时,这个线程就获得了当前对象的锁。
//其他线程调用同步方法时只能等待。
public int getMoney(int number){
synchronized (this ) {
if(number<0){
return -1;
} else if (money <0){
return -2;
} else if (number-money >0){
return -3;
} else{
try {
Thread. sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
money-=number;
System. out.println(“取钱:” +number);
}
}
return money ;
}
}
同步产生死锁的原因:
当一个线程已经获得了对象1的锁,同时又想获得对象2的锁,同时有一线程获得对象2的锁
又想获得对象1的锁,这种相互等待对方释放锁的过程,称为死锁。
线程间的通信:
主要方法:wait()
在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。换句话说,此方法的行为就好像它仅执行 wait(0) 调用一样
notify()
唤醒在此对象监视器上等待的单个线程。
notifyAll()
唤醒在此对象监视器上等待的所有线程。
多线程加锁/释放锁, 经典的消费者/生产者的问题:
eg: 假设仓库中只放一种产品,生产者将产品生产出来放入仓库,消费者将仓库中产品拿出来
如果仓库中没有产品,生产者生产产品,将产品放入仓库,否则停止生产并等待,知道仓库中产
品被消费者取完为止。如果仓库中有产品消费者取走产品,否则停止消费直到仓库中放入产品。
代码:import java.util.LinkedList;
public class ProductorConsumerDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Basket basket= new Basket();
Productor productor= new Productor(basket);
Consumer consumer= new Consumer(basket);
productor.start();
consumer.start();
}
}
//消费者类
class Consumer extends Thread{
private Basket basket =null;
public Consumer(Basket basket) {
super();
this.basket = basket;
}
//重写run方法 ,实现篮子里取苹果。
public void run() {
// TODO Auto-generated method stub
basket.popApple();
}
}
//工厂类
class Productor extends Thread{
private Basket basket =null;
public Productor(Basket basket) {
super();
this.basket = basket;
}
//重写run方法,实现工厂篮子里放苹果
public void run() {
// TODO Auto-generated method stub
basket.pushApple();
}
}
class Basket{
private LinkedList basket =new LinkedList();
//放4轮苹果,
public synchronized void pushApple(){
for (int i = 0; i < 20; i++) {
Apple apple= new Apple(i);
push(apple);
}
}
//取四轮苹果。
public synchronized void popApple(){
for (int i = 0; i < 20; i++) {
pop();
}
}
//向篮子里放苹果。
private void push(Apple apple){
//当篮子里的苹果为5时,通知消费者取苹果。
if (basket .size()==5) {
try {
//苹果到达数量后方苹果等待。
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
Thread. sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
basket.addFirst(apple);
System. out.println("存放" +apple.toString());
notify(); //通知消费者取苹果。
}
//篮子里取苹果。
private void pop(){
//当篮子里苹果为0时。停止取,并通知生产在者生产。
if (basket .size()==0) {
try {
//苹果到达数量后方苹果等待。
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
Thread. sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Apple apple = basket.removeFirst();
System. out.println("吃掉" +apple.toString());
notify(); //通知生产者来生产。
}
}
class Apple{
private int id ;
//创建Apple类的构造方法,设置其id.
public Apple(int id){
this.id =id;
}
//重写toString方法。
public String toString() {
return “苹果:” +(id +1);
}
}