Cpu内部是串行的是分时执行,在外面是并行的
多线程
1 继承 Thread类 中public void run()
2 实现 Runnable接口 实现public void run()
阻塞状态 |
T2阻塞,t1继承运行 |
初始状态 |
终止状态 |
1 等待输入 2 thread。sheep() 3 t2:t1.join() |
Os选 中
可运行状态 |
运行状态 |
public class TestThread {
public static void main(String[] args) {
Thread t1=new ThreadA();
Runnable target=new Target();
Thread t2=new Thread(target);
t1.start();
t2.start();
}
}
class ThreadA extends Thread{
public void run(){
for(int i=1;i<=100;i++){
System.out.println(i+" $$$");
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
}
}
}
class Target implements Runnable{
public void run(){
for(int i=1;i<=100;i++){
System.out.println(i+" ###");
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
}
}
}
结果:
1 $$$
1 ###
2 ###
2 $$$
3 ###
3 $$$
4 $$$
4 ###
5 $$$
5 ###
6 ###
6 $$$
7 ###
7 $$$
8 $$$
8 ###
9 $$$
9 ###
10 $$$
10 ###
11 $$$
11 ###
12 $$$
线程:进程中并发的一个顺序执行流程
并发原理:CPU分时间片,多线程交替运行
宏观并行,微观串行
线程三要素:CPU Data Code
多线程间堆空间共享,栈空间独立
创建线程两种方式:继承Thread类,实现Runnable接口
Thread对象代表了一个线程
多线程共同访问了同一个对象(临界资源),如何破坏了不可分割的操作(原子操作),就会造成数据不一致的情况
在Java中,任何对象都有一个互斥锁标记,用来分配给线程.
synchronized(o){} 对o加锁的同步代码块
只有拿到o的锁标记的线程,才能进入对o加锁的同步代码快,退出同步代码块,会自动释放o的锁标记
public synchronized void m(){} 同步方法,对this加锁
哪个线程能拿到对象的锁,哪个线程就能调用对象的同步方法
在Java中,任何对象都有一个锁池,用来存放等待该对象锁标记的线程
一个线程,可以同时拥有多个对象的锁标记,线程阻塞在对象锁池中时,不会释放其所拥有的其他对象的锁标记
在Java中,任何对象都有一个等待队列,用来存放线程
t1对o调用wait方法,必须放在对o加锁的同步代码块中! 1.t1会释放其所拥有的所有锁标记;2.t1会进入o的等待队列
t2对o调用notify/notifyAll方法,也必须放在对o加锁的同步代码块中! 会从o的等待队列中释放一个/全部线程 对t2毫无影响
public class TestProducerConsumer {
public static void main(String[] args) {
MyStack ms=new MyStack();
Thread t1=new Producer(ms);
Thread t2=new Consumer(ms);
t1.start();
t2.start();
}
}
class MyStack{
char[] data=new char[6];
int index=0;
private void print(){
for(int i=0;i<index;i++){
System.out.print(data[i]+" ");
}
System.out.println();
}
public synchronized void push(char c){
while(index==data.length){
try {
this.wait();
} catch (InterruptedException e) {}
}
System.out.print(c+" pushed! ");
data[index]=c;
index++;
this.notifyAll();
print();
}
public synchronized void pop(){
while(index==0){
try {
this.wait();
} catch (InterruptedException e) {}
}
index--;
System.out.print(data[index]+" poped! ");
data[index]=' ';
this.notifyAll();
print();
}
}
class Producer extends Thread{
MyStack ms;
public Producer(MyStack s){
this.ms=s;
}
public void run(){
for(char c='A';c<='Z';c++){
ms.push(c);
}
}
}
class Consumer extends Thread{
MyStack ms;
public Consumer(MyStack s){
this.ms=s;
}
public void run(){
for(int c=1;c<=26;c++){
ms.pop();
}
}
}
public class TestNumberCharPrint {
public static void main(String[] args) {
Object o=new Object();
Thread t1=new NumberThread(o);
Thread t2=new CharThread(o);
t1.start();
t2.start();
}
}
class NumberThread extends Thread{
Object o;
public NumberThread(Object o){
this.o=o;
}
public void run(){
synchronized (o) {
for (int i = 1; i <= 26; i++) {
System.out.println(i * 2 - 1);
System.out.println(i * 2);
o.notifyAll();
try {
if (i!=26) o.wait();
} catch (InterruptedException e) {
}
}
}
}
}
class CharThread extends Thread{
Object o;
public CharThread(Object o){
this.o=o;
}
public void run(){
synchronized (o) {
for (char c = 'A'; c <= 'Z'; c++) {
System.out.println(c);
o.notifyAll();
try {
if (c!='Z') o.wait();
} catch (InterruptedException e) {}
}
}
}
}
结果:
A
1 2
B
3 4
………