初步认识:
1、synchronized 被访问时自动获取所在对象的锁。
2、wait() 使当前进程进入阻塞状态并释放锁。
3、notify() / notifyAll() 唤醒处于阻塞状态的进程。
4、进程要获得锁才能运行。
两类线程问题:
双线程和多线程(3个及以上)
只执行同一任务,使用synchronized同步即可,
多任务需要配合wait()、notify() / notifyAll()
注意两点:
1 循环表达式3的位置要和目的执行语句同步执行。
2 明确目的执行语句
是要不满足条件且wait()后就可执行(双线程不同任务,另一线程使得满足条件)
还是要同步执行(多线程同任务)
还是只在满足条件时执行(多线程不同任务)。
1、双线程不同任务
实例2 写2个线程,其中一个线程打印1~26,另一个线程打印A~Z,1对A,2对B。
这个问题在不满足条件后wait()就可执行是因为,只有两个线程,且一个线程执行后,一定会使另一个线程满足条件。
代码:
import java.util.*;
import java.io.*;
class chik {
int i = 1;
private boolean isOk = true;
public synchronized void ptN() {
if(isOk == false) {
try {
wait();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
System.out.print(i);
isOk = false;
notify();
}
public synchronized void ptC() {
if(isOk == true) {
try {
wait();
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println((char)(i + 64));
i++;
isOk = true;
notify();
}
}
class ptN extends Thread {
chik ck;
public ptN(chik ck) {
this.ck = ck;
}
@Override
public void run() {
for(int i = 0; i < 26;i++)
ck.ptN();
}
}
class ptC extends Thread{
chik ck;
public ptC(chik ck) {
this.ck = ck;
}
@Override
public void run() {
//此循环也可以放在ck类里面
for(int i = 0; i < 26;i++)
ck.ptC();
}
}
public class Main {
public static void main(String [] args) {
chik ck = new chik();
ptN pn = new ptN(ck);
ptC pc = new ptC(ck);
pn.start();
pc.start();
}
}

2、多线程完成同一任务
问题实例:
实例1 一个计数器,计数0到19,在每个数字之间暂停1秒,每隔10个数字输出一个字符串。
代码:
import java.util.*;
import java.io.*;
class Counter{
int x;
public Counter() {}
public Counter(int x) {
this.x = x;
}
}
class RunTd implements Runnable{
Counter counter;
public RunTd() {}
public RunTd(Counter counter) {
super();
this.counter = counter;
}
public void run() {
print();
}
public void print() {
synchronized(counter) {
for(;counter.x < 20;counter.x++) {
if(counter.x % 10 == 0) System.out.println("------" + counter.x);
System.out.println(counter.x + "线程睡眠1毫秒!");
}
try {
Thread.sleep(1);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
}
class Main{
public static void main(String[] args) {
Counter count = new Counter(0);
new Thread(new RunTd(count)).start();
new Thread(new RunTd(count)).start();
new Thread(new RunTd(count)).start();
}
}

3、多线程按顺序完成不同任务
问题描述实例:
启动3个线程 要求为每个线程单独输输入一个字符或字符串, 并按顺序输出三次,例线程1输入a,线程2输入b,线程三输入c,要求结果输出是a b c a b c a b c 这种连续的字符串(最后c后面有一个空格)
代码:
import java.util.*;
import java.io.*;
class Counter{
int x;
public Counter() {}
public Counter(int x) {
this.x = x;
}
}
class RunTd implements Runnable{
Counter counter;
String str;
int id;
public RunTd(Counter counter, String str, int id) {
super();
this.counter = counter;
this.str = str;
this.id = id;
}
@Override
public void run() {
print();
}
public void print() {
synchronized(counter) {
//*****输出后i再++,!=id就不输出*****
//此循环若放在counter里面,会漏掉一些值
for(int i = 0;i < 3;) {
if(counter.x != id)
try {
counter.wait();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
else {
System.out.print(str + " ");
counter.x = (counter.x + 1) % 4;
if(counter.x == 0) counter.x = 1;
i++;
counter.notifyAll();
}
}
}
}
}
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Counter count = new Counter(1);
new Thread(new RunTd(count, sc.next(), 1)).start();
new Thread(new RunTd(count, sc.next(), 2)).start();
new Thread(new RunTd(count, sc.next(), 3)).start();
sc.close();
}
}
输入A B C

本文介绍Java多线程相关知识,包括synchronized、wait()、notify()等方法的作用,进程运行需获得锁。阐述了双线程和多线程两类问题,针对不同任务场景给出解决思路,并通过实例展示双线程不同任务、多线程完成同一任务、多线程按顺序完成不同任务的代码实现。

被折叠的 条评论
为什么被折叠?



