多线程
1.基本概念:程序、进程、线程
-
程序:为完成特定任务,用某种语言编写成的指令集合
-
进程: 程序的一次执行,或正在运行的程序。如QQ、微信等,时资源分配的单位
-
线程: 进程可进一步细化为线程,是一个进程内部执行的一次路径,一个进程至少有一个或者多个线程。线程作为调用和执行的单位,每个线程拥有独立的运行栈和程序计数器,多个线程共享进程的方法区和堆的资源。
-
多线程: 如运行了QQ进程后,可以发送文件,也可以同时下载文件。
-
并发:一个时间段内,多个任务按照分配时间片依次进行
-
并行:一个时间段内,多个任务同时进行
2.线程的创建和使用(4种方式)
-
start方法:开启线程,并调用run方法(线程在被调度时执行的操作 )
-
1.继承Thread类重写run()方法
public static void main(String[] args) {
FirstThread firstThread = new FirstThread();
firstThread.start();
FirstThread firstThread1 = new FirstThread();
firstThread1.start();
new Thread(){
@Override
public void run() {
for (int i = 0; i < 100 ; i++) {
if(i % 2 == 0){
System.out.println(i);
}
}
}
}.start();
new FirstThread().start();
}
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
new Thread(new myRunnable()).start();
public static void main(String[] args) {
MyThreadApi myThreadApi = new MyThreadApi();
new Thread(new MyThreadApi()).start();
myThreadApi.start();
Thread.currentThread().getName();
myThreadApi.currentThread().getName();
Thread.currentThread().setName("主线程:");
myThreadApi.setName("我是myThreadApi种的线程:");
}
两种实现多线程方式对比
-
1.开发中优先选择实现Runnable接口方式:
-
A.没有单继承局限性
-
B.更适合来处理多个线程共享数据的情况
3线程的生命周期
4线程的同步(同步代码块,同步方法,Lock锁 [ lock(),unlock()方法 ])
-
实现Runnable接口解决线程安全问题(代码块)
private int ticket = 100;
private Object obj = new Object();
@Override
public void run() {
while (true){
synchronized(obj){
if(ticket > 0){
ticket--;
System.out.println(Thread.currentThread().getName() + "购票成功! 剩余票数:" + ticket);
}else {
break;
}
}
}
}
public static void main(String[] args) {
RunnableTicket runnableTicket = new RunnableTicket();
new Thread(runnableTicket).start();
new Thread(runnableTicket).start();
}
private int ticket = 100;
@Override
public void run() {
while(true){
show();
}
}
private synchronized void show(){
if(ticket > 0){
ticket--;
System.out.println(Thread.currentThread().getName() + "购票成功! 剩余票数:" + ticket);
}else {
break;
}
}
private static int ticket = 100;
private static Object obj = new Object();
@Override
public void run() {
while (true){
synchronized(obj){
if(ticket > 0){
ticket--;
System.out.println(Thread.currentThread().getName() + "购票成功! 剩余票数:" + ticket);
}else {
break;
}
}
}
}
public static void main(String[] args) {
new ThreadTicket().start();
new ThreadTicket().start();
}
private static int tickets = 100;
@Override
public void run() {
while (true){
show();
}
}
private static synchronized void show(){
if(tickets > 0){
tickets--;
System.out.println("售票成功! 当前乘车人:" + Thread.currentThread().getName() + ",剩余票数:" + tickets);
}else {
return;
}
}
-
例题:两个账户向另一个账户汇款各3000元,共3次
public class ImportMoney {
private static int money = 0;
public synchronized void getMoney(int getMoney){
if(getMoney > 0){
money += getMoney;
System.out.println("当前余额: " + money + ",汇款账户:" + Thread.currentThread().getName());
}else {
return;
}
}
public void getMoney(int getMoney){
synchronized(this){
if(getMoney > 0){
money += getMoney;
System.out.println("当前余额: " + money + ",汇款账户:" + Thread.currentThread().getName());
}else {
return;
}
}
}
}
public class ImportMoneyTest {
public static void main(String[] args) {
ImportMoney in = new ImportMoney();
new Export(in).start();
new Export(in).start();
}
}
class Export extends Thread{
private ImportMoney importMoney;
public Export(ImportMoney importMoney){
this.importMoney = importMoney;
}
@Override
public void run() {
for (int i = 0; i <3 ; i++) {
importMoney.getMoney(1000);
}
}
}
5线程的通信
public class MyWait implements Runnable {
private int num = 1;
@Override
public void run() {
while (true){
synchronized (this){
notify();
if(num <= 100){
System.out.println(Thread.currentThread().getName() + ":" + num);
num++;
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
break;
}
}
}
}
}
6 JDK5.0新增线程创建方式(共4种)