文章目录
写在前面
1、单线程的创建
1 继承Thread类 (里面实际上也是实现的Runnable接口)
2 实现runable接口 (没返回值)
3 实现callable接口 (有返回值)
1.1、继承Thread类使用示例
class Mythread extends Thread{
@Override
public void run() {
for(int i=0;i<100;i++){
if(i%2==0){
System.out.println(i);
}
}
}
}
调用
public static void main(String[] args) {
// 用start()来启动线程,此时会出现异步执行的效果。
// 用run()来启动线程,就不是异步执行了,而是同步执行,不会达到使用线程的意义。
new Thread1().start();
}
或者直接这样
public static void main(String[] args) {
new Thread(){
@Override
public void run() {
for(int i=0;i<100;i++){
if(i%2==0){
System.out.println("1222:"+i);
}
}
}
}.start();
}
1.2、实现runable接口使用示例
public class Thread2 implements Runnable{
private int ticket;
public Thread2(int ticket){
this.ticket=ticket;
}
@Override
public void run(){
while (ticket>0){
ticket--;
System.out.println("剩余"+ticket+"张票");
}
}
}
调用
public static void main(String[] args) {
Runnable r = new Thread2(100);
new Thread(r).start();
}
或者直接这样
public static void main(String[] args) {
Runnable r = new Runnable() {
private int ticket = 100;
@Override
public void run() {
while (ticket > 0) {
ticket--;
System.out.println("剩余" + ticket + "张票");
}
}
};
new Thread(r).start();
}
1.3、实现callable接口使用示例
public class Thread3 implements Callable {
@Override
public Object call() throws Exception {
for(int i=0;i<100;i++){
if(i%2==0){
System.out.println(i);
}
}
return "ok";
}
}
调用
public static void main(String[] args) {
Thread3 r = new Thread3();
FutureTask futureTask = new FutureTask(r);
Thread t1 = new Thread(futureTask);
t1.start();
try {
//get()方法的返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值
Object rsl = futureTask.get();
System.out.println(rsl);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
2、sleep和wait的区别
方法名 | 区别 |
---|---|
sleep() | 暂停一段时间后恢复,没有释放锁,必须抛异常。用于当前线程 |
wait() | 需要被唤醒,释放了锁,必须抛异常。用于多线程间通信 |
2.1、使用wait需要注意
使用 wait 方法则必须放在 synchronized 块里面,同样需要捕获 InterruptedException 异常,并且需要获取对象的锁。
synchronized (lock){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
而且 wait 还需要额外的方法 notify/ notifyAll 进行唤醒,它们同样需要放在 synchronized 块里面,且获取对象的锁。
synchronized (lock) {
// 随机唤醒
lock.notify();
// 唤醒全部
lock.notifyAll();
}
当然也可以使用带时间的 wait(long millis) 方法,时间一到,无需其他线程唤醒,也会重新竞争获取对象的锁继续执行。
2.2、释放锁
Object lock = new Object();
synchronized (lock) {
try {
lock.wait(3000L);
Thread.sleep(2000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
如上,wait 可以释放当前线程对 lock 对象锁的持有,而 sleep 则不会。