进程:运行中的应用程序,每个进程都有独立的内存空间.一个应用程序可以同时启动多个进程. 一个进程可以有多个线程组成,他们分别执行不同的任务,当进程的多个线程同时运行时,这种运行方式称并发运行.
进程与现在的主要区别是:每个进程都需要操作系统为其分配独立的内存地址空间,而同一进程下的多有线程在同一块地址空间中工作,这些线程可以共享同一个资源,空间.
进程:运行中的应用程序,每个进程都有独立的内存空间.一个应用程序可以同时启动多个进程. 一个进程可以有多个线程组成,他们分别执行不同的任务,当进程的多个线程同时运行时,这种运行方式称并发运行.
进程与现在的主要区别是:每个进程都需要操作系统为其分配独立的内存地址空间,而同一进程下的多有线程在同一块地址空间中工作,这些线程可以共享同一个资源,空间.
public class Sample {
private int a; //实例变量
public int method() {
int b = 0; //局部变量
a++;
b = a;
return b;
}
public static void main(String[] args) {
Sample s = null;
int a = 0;
s = new Sample();
a = s.method();
System.out.println(a);
}
}
2. 线程的创建与启动
创建线程可以继承Thread 或 实现 runnable接口
Ø Thread 主要有两个方法:run()包含线程运行时所执行的代码,start()用于启动线程。用户继承了thread类,覆盖了run()方法。
public class Machine extends Thread {
public void run() {
//线程所执行的代码
for(int a=0;a<50;a++) {
System.out.println(a);
}
}
public static void main(String[] args) {
Machine m = new Machine();
m.start();//启动Machine线程
}
}
public class Machine extends Thread {
public void run() {
//线程所执行的代码
for(int a=0;a<50;a++) {
System.out.println(currentThread().getName()+":"+a);
try {
sleep(100); //给其他线程运行机会
}catch(InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) {
Machine m1 = new Machine(); //创建第一个Machine对象
Machine m2 = new Machine();//创建第二个Machine对象
m1.start();//启动Machine线程
m2.start();//启动Machine线程
m1.run();//执行第一个Machine对象的run方法
}
}
Thread 的currentThread()放回当前线程的引用,.getName()返回线程名字。每个线程都有默认的名字,主线程名字为main,用户第一个线程名字是thread-0,第二个是thread-1,依次类推。Setname可以设置线程的名字。
为了让每个线程都轮流获得CPU,在run方法中还调用了thread类的sleep静态方法,该方法让当前的现象进入睡眠状态.
1. 多个线程共享同一个对象的实例变量
上个例子中a是Machine的一个实例变量。Machine的run方法使用了这个变量。
一个线程只能被启动一次,即被start一次。
不但可以继承thread还可以实现runnable接口
public class Machine implements Runnable {
public void run() {
//线程所执行的代码
for(int a=0;a<50;a++) {
System.out.println(Thread.currentThread().getName()+":"+a);
try {
Thread.sleep(1000); //给其他线程运行机会
}catch(InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) {
Machine m = new Machine(); //创建Machine对象
Thread t1 = new Thread(m);
Thread t2 = new Thread(m);
t1.start();//启动Machine线程
t2.start();//启动Machine线程
t1.run();//执行第一个Machine对象的run方法
}
}
2. 线程的状态转换
3. 新建状态new:和其他Java对象一样,紧紧在堆区分配了内存。
4. 就绪状态runnable
5. 运行状态running
6. 阻塞状态blocked
7. 死亡状态dead
8. 线程调度:分分时调度和抢占式调度。
9. 线程睡眠:thread.sleep方法
10. 线程让步 thread.yield方法
11. 等待其他线程结束 join()
12. 获得当前线程对象的引用
13. 后台线程
14. 定时器timer
15. 线程的同步
16. 同步代码块
17. 线程同步特征
18. 同步于并发
public class Well {
private int water = 1000;
public void withdraw() { //打一桶水
System.out.println(Thread.currentThread().getName()+":water left:"+water);
}
}
public class Person extends Thread {
private Well well;
public Person(Well well) {
start();//启动自身线程
}
public void run() {
synchronized (well) {
for(int i=0;i<10;i++) {
well.withdraw();//打10桶水
yield();
}
}
}
public static void main(String[]args) {
Well w = new Well();
Person p[] = new Person[10]; //创建10个person线程
for(int i=0;i<10;i++) {
p[i] = new Person(w);
}
}
}
为了提高并发性能,应该使同步代码中包含尽可能少的操作,使得一个线程能够尽快释放锁。减少对其他线程的等待时间。
那就取消对run方法的同步,在well时给同步就可以了。
public class Well {
private int water = 1000;
public synchronized void withdraw() { //打一桶水
System.out.println(Thread.currentThread().getName()+":water left:"+water);
}
}
--
public class Person extends Thread {
private Well well;
public Person(Well well) {
start();//启动自身线程
}
public void run() {
for(int i=0;i<10;i++) {
well.withdraw();//打10桶水
yield();
}
}
public static void main(String[]args) {
Well w = new Well();
Person p[] = new Person[10]; //创建10个person线程
for(int i=0;i<10;i++) {
p[i] = new Person(w);
}
}
}
19. 释放锁对象
public class Machine extends Thread {
private int a = 1;
public synchronized void print() {
System.out.println("a:"+a);
}
public void run() {
synchronized (this) {
try {
sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
a++;
}
}
public static void main(String[] args) {
Machine m = new Machine();
m.start();
Thread.yield();
m.print();
}
}
20. 死锁:当一个线程等待由另一个线程持有的锁,而另一个正在等待已被第一个线程持有的锁时,就会发生死锁。下面这个就会导致死锁。
21. 线程通信:不同的线程执行不同的任务,如果这些任务有某种关系,线程之间必须能通信。通信的方法:wait:执行该方法的线程释放对象的锁,Java虚拟机把该线程放到该对象的等待池中,该线程等待其他线程将它唤醒。Notify:执行该方法的线程唤醒在对象的等待池中等待的一个线程。Java虚拟机从对象的等待池中随机选择一个线程,把它传到对象的锁池中。