1.进程与线程
一个程序只有一个进程
一个进程包含多个线程(必须有一个主线程)
查看线程
public static void main(String args[]) {Thread t = Thread.currentThread(); //获得当前线程System.out.println("当前线程是: "+t.getName()); t.setName("MyJavaThread"); //更改线程的名字System.out.println("当前线程名是: "+t.getName());
}
2.线程的创建方式
(1)继承Thread类
继承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 t1 = new MyThread();//创建第一个线程t1.start(); //启动线程MyThread t2 = new MyThread();//创建第二个线程t2.start(); //启动线程
}
(2)实现Runnable接口
实现Runnable接口,实现run()方法,调用start()方法启动线程
public class MyRunnable implements Runnable{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 t = new Thread(myRunnable); t.start(); //启动线程
}
(3)实现Callable接口
实现Callable<数据类型>,重写call方法 注意:Callable有返回值
/*
*子线程
*/
public class MyCallable implements Callable<String> {
//重写call方法@Overridepublic String call() throws Exception {//子线程执行的任务for (int i=0;i<20;i++){System.out.println(java.lang.Thread.currentThread().getName()+"===="+i);}return "这是MyCallable";}
}
public static void main(String[] args) {
//FutureTask-->RunnableFuture -->RunnableMyCallable myCallable = new MyCallable();
// FutureTask是一个实现了Runnable接口的类FutureTask<String> ft = new FutureTask<String>(myCallable);
java.lang.Thread t1 = new java.lang.Thread(ft);t1.start();//启动线程
try {//获得返回值System.out.println(ft.get());} catch (Exception e) {e.printStackTrace();}
}
3.线程状态
创建状态:new Thread时
就绪状态:调用start()方法
运行状态:执行run()方法
阻塞状态:调用sleep,join 会进入阻碍状态,恢复后改为就绪状态-->运行状态
死亡状态:run()运行结束
4.线程常用方法
方 法 | 说 明 |
---|---|
void setPriority(int newPriority) | 更改线程的优先级 |
static void sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程休眠 |
void join() | 等待该线程终止 |
static void yield() | 暂停当前正在执行的线程对象,并执行其他线程 |
void interrupt() | 中断线程 |
boolean isAlive() | 测试线程是否处于活动状态 |
wait() | 暂停一个线程 |
notify | 唤起一个线程 |
注意:join写在哪个线程阻塞谁,谁就调用谁强制执行
sleep使用毫秒 1000ms =1s
//优先级
Priority p = new Priority();
Thread t1 = new Thread(p,"A");
t1.setPriority(10);
t1.start();
Thread t2 = new Thread(p,"B");
t2.setPriority(1);
t2.start();
//睡眠2秒
Thread.sleep(2000);
//查看线程活动
System.out.println(t.isAlive());
5.线程安全
多个线程一起操作同意共享资源时,将引发数据不安全问题
同步方法(synchronized)
使用synchronized修饰的方法控制对类成员变量的访问
synchronized就是为当前的线程声明一把锁
1.修饰方法体
public synchronized void sale() { if (count <= 0) {flag = true;return;}
}
2.修饰代码块
public void run() {synchronized (this) { //放同步代码块}
}
线程安全的类型
查看ArrayList类的add()方法定义
public boolean add(E e) {ensureCapacityInternal(size + 1); //集合扩容,确保能新增数据elementData[size++] = e;//在新增位置存放数据return true;
}
ArrayList类的add()方法为非同步方法
当多个线程向同一个ArrayList对象添加数据时,可能出现数据不一致问题
常见类型对比
1.Hashtable && HashMap
Hashtable | HashMap |
---|---|
继承关系 :实现了Map接口,Hashtable继承Dictionary类 | 继承关系:实现了Map接口,继承AbstractMap类 |
线程安全,效率较低 | 非线程安全,效率较高 |
键和值都不允许为null | 键和值都允许为null |
2.StringBuffer && StringBuilder
StringBuffer | StringBuilder |
---|---|
线程安全 | 非线程安全 |