@wangyupu
2020-07-14T11:08:03.000000Z
字数 4108
阅读 27
JAVA高级编程
如果在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为“多线程”**
多个线程交替占用CPU资源,而非真正的并行执行
充分利用CPU的资源
简化编程模型
带来良好的用户体验
Thread类
Java提供了`java.lang.Thread`类支持多线程编程
main()方法即为主线程入口
产生其他子线程的线程
必须最后完成执行,因为它执行各种关闭动作
public static void main(String args[]) {
Thread t= Thread.currentThread();
//输出线程名
System.out.println("当前线程是: "+t.getName());
//更改线程名
t.setName("MyJavaThread");
System.out.println("当前线程名是: "+t.getName()); }
使用线程的步骤
1.定义线程---2.创建线程对象---3.启动线程---4.终止线程
Thread类
定义`MyThread`类继承Thread类
重写run()方法,编写线程执行体
创建线程对象,调用start()方法启动线程
public class MyThread extends Thread{
//重写run()方法
public void run(){
for(int i=1;i<100;i++){ System.out.println(
Thread.currentThread().getName()+":"+i);
}
}
}
public static void main(String[] args) {
MyThread thread1 = new MyThread();
thread1.start(); //启动线程1
MyThread thread2 = new MyThread();
thread2.start(); //启动线程2
}
//多个线程交替执行,不是真正的“并行”
//线程每次执行时长由分配的CPU时间片长度决定
定义`MyRunnable`类实现Runnable接口
实现run()方法,编写线程执行体
创建线程对象,调用start()方法启动线程
//实现Runnable接口
public class MyRunnable implements Runnable{
//run()方法中编写线程执行的代码
public void run(){
for(int i=1;i<100;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
public static void main(String[] args) {
//创建线程对象
MyRunnable myRunnable = new MyRunnable();
Thread myThread = new Thread(myRunnable);
thread.start(); //启动线程}
编写简单,可直接操作线程
适用于单继承
避免单继承局限性
便于共享资源
创建状态---就绪状态---阻塞状态--运行状态--死亡状态**
方 法 | 说 明 |
---|---|
void setPriority(int newPriority) | 更改线程的优先级 |
static void sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程休眠 |
void join() | 等待该线程终止 |
static void yield() | 暂停当前正在执行的线程对象,并执行其他线程 |
void interrupt() | 中断线程 |
boolean isAlive() | 测试线程是否处于活动状态 |
线程优先级由1~10表示,1最低,默认优先级为5
优先级高的线程获得CPU资源的概率较大
public static void main(String[] args) {
Thread t1 = new Thread(new MyThread(),"线程A");
Thread t2 = new Thread(new MyThread(),"线程B");
t1.setPriority(Thread.MAX_PRIORITY);
t2.setPriority(Thread.MIN_PRIORITY);
//……
}
}
//两个线程对象分别设置为最高优先级和最低优先级
让线程暂时睡眠指定时长,线程进入阻塞状态
睡眠时间过后线程会再进入可运行状态
public static void sleep(long millis)
//millis为休眠时长,以毫秒为单位
//调用sleep()方法需处理InterruptedException异常
public class Wait {
public static void bySec(long s) {
for (int i = 0; i < s; i++) {
System.out.println(i + 1 + "秒");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public final void join()
public final void join(long mills)
public final void join(long mills,int nanos)
/*millis:以毫秒为单位的等待时长
nanos:要等待的附加纳秒时长
需处理InterruptedException异常
*/
public static void main(String[] args) {
Thread temp = new Thread(new MyThread());
temp.start();
for(int i=0;i<20;i++){
if(i==5){
try {
temp.join();
} catch (InterruptedException e) {
e.printStackTrace(); }}
System.out.println(Thread.currentThread().getName()+"运行:"+i);
}
}
/*暂停当前线程,允许其他具有相同优先级的线程获得运行机会
该线程处于就绪状态,不转为阻塞状态
*/
public static void yield()
//只是提供一种可能,但是不能保证一定会实现礼让
public class MyThread implements Runnable{
public void run(){
for(int i=0;i<5;i++){
System.out.println(Thread.currentThread().
getName()+"正在运行:"+i);
if(i==3){
System.out.print("线程礼让:");
Thread.yield();
}
}
}
}
public void run(){
while(true){
//省略代码:判断是否余票
num++;
count--;
try {
Thread.sleep(500); //模拟网络延时
} catch (InterruptedException e) {//…}
System.out.println(Thread.currentThread().getName()
+"抢到第"+num+"张票,剩余"+count+"张票!");
}
}
//多个线程操作同一共享资源时,将引发数据不安全问题
//使用synchronized修饰的方法控制对类成员变量的访问
访问修饰符 synchronized 返回类型 方法名(参数列表){……}
//或者
synchronized 访问修饰符 返回类型 方法名(参数列表){……}
//synchronized就是为当前的线程声明一把锁
// 同步方法:售票
public synchronized void sale() {
if (count <= 0) {
flag = true;
return;
}
// 省略代码:修改数据
// 省略代码:显示信息
}
//使用synchronized关键字修饰的代码块
synchronized(syncObject){
//需要同步的代码
}
//syncObject为需同步的对象,通常为this
//效果与同步方法相同
public void run() {
while (true) {
synchronized (this) { //同步代码块
// 省略修改数据的代码......
// 省略显示信息的代码......
}
}
}
多个并发线程访问同一资源的同步代码块时
- 同一时刻只能有一个线程进入synchronized(this)同步代码块
- 当一个线程访问一个synchronized(this)同步代码块时,其他synchronized(this)同步代码块同样被锁定
- 当一个线程访问一个synchronized(this)同步代码块时,其他线程可以访问该资源的非synchronized(this)同步代码
//查看ArrayList类的add()方法定义
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
//ArrayList类的add()方法为非同步方法
//当多个线程向同一个ArrayList对象添加数据时,可能出现数据不一致问题
方法是否同步 | 效率比较 | 适合场景 |
---|---|---|
线程安全 | 是 | 低 |
非线程安全 | 否 | 高 |
Hashtable
&&HashMap
Hashtable
继承关系
实现了Map接口,
Hashtable
继承Dictionary
类 线程安全,效率较低
键和值都不允许为null
HashMap
继承关系
实现了Map接口,继承
AbstractMap
类 非线程安全,效率较高
键和值都允许为null
StringBuffer
&&StringBuilder
- 前者线程安全,后者非线程安全