1.实现runable
2.继承Thread
3.重写callable接口重写call方法
1.5后,返回一个参数
线程和进程:
进程:
占用计算机一定的cpu ,内存 ,带宽等资源的一个应用如(.exe ,qq)
一个操作系统包括多个进程
线程:
qq是一个进程,会占用一定的资源
qq同时和多个人进行聊天的时候,是相互独立的,这就是多线程
一个进程包含多个线程
锁的两种实现:
JDK 提供了两种锁:
Synchronized是一种同步锁,通过锁实现原子操作,修饰的对象有四种:(1)修饰代码块(2)修饰方法(3)修饰静态方法(4)修饰类。
另一种是LOCK,是JDK提供的代码层面的锁。
创建线程方式一:实现runable
/**
* 方法一:实现runnable接口,并实现该接口的run()方法。
*
* 以下是主要步骤:
* ①自定义类并实现Ruannable接口,实现run()方法。
* ②创建Thread对象,用实现Ruannable接口的独享作为参数实例化该Thread对象。
* ③调用Thread的start()方法;
*/
public class MyThread implements Runnable{
@Override
public void run() {
say();
}
//加锁的方法
synchronized public void say(){
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName());
}
}
}
测试代码:
public class Runnable_Thread_Demo1 {
public static void main(String[] args) {
MyThread myThread = new MyThread();
Thread t1 = new Thread(myThread,"t1");
Thread t2 = new Thread(myThread,"t2");
t1.start();
t2.start();
}
}
创建线程方式二:继承Thread
/**
* 方式二:
* 继承Thread类,重写run方法。
* Thread类本质上是实现了Runnable接口的一个实例
*/
public class MyThread extends Thread{
@Override
public void run() {
say();
}
//加锁的方法
synchronized public void say(){
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName());
}
}
public MyThread() {
}
//new MyThread的时候传入姓名,需要用到这个方法
public MyThread(String name) {
super(name);
}
}
测试代码:
public class Thread_Thread_Demo2 {
public static void main(String[] args) {
MyThread m1 = new MyThread();
MyThread m2 = new MyThread();
m1.start();
m2.start();
// MyThread m3 = new MyThread("m1");//这样要重写MyThread的构造方法
}
}
创建线程方式三:重写callable接口重写call方法
import java.util.concurrent.Callable;
/**
* 方式三:
* 实现Callable接口,重写call方法。
* 使用ExecutorService,Callable,Future实现带返回结果的多线程。
*
* 如果有这样的一个场景,需要让异步执行的线程在执行完成后返回一个值给当前的线程,
* 当前的线程需要依赖这个值做一些其他的业务操作,这个时候就要用到如下带返回值的线程了。
*/
public class MyThread implements Callable<String> {
@Override
public String call() throws Exception {
say();
return "callable中call方法返回的值";
}
synchronized public void say(){
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName());
}
}
}
测试代码:
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* Callable接口是Java1.5开始出现的只有一个带返回值的call()方法
* 步骤:
* 1.ExecutorService启动线程
* 2.实例化一个自己写的线程类
* 3.Future接收返回的参数
* 4.Future.get取得返回值(get方式会阻塞,需要抛出异常)
*/
public class Callable_Thread_demo3 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// ExecutorService启动线程
ExecutorService executorService = Executors.newCachedThreadPool();
// ExecutorService executorService1 = Executors.newSingleThreadExecutor();//多种启动方式
// 实例化一个自己写的线程类
MyThread m1 = new MyThread();
MyThread m2 = new MyThread();
// Future接收返回的参数
Future<String> submit = executorService.submit(m1);
Future<String> submit2 = executorService.submit(m2);
System.out.println(submit.get());//get方式会阻塞,需要抛出异常
System.out.println(submit2.get());
//关闭
executorService.shutdown();
}
}
sleep 和 wait的区别?
1. sleep(毫秒)
放弃CPU的执行权;
但是不会放弃锁;
2.wait(可选)
放弃CPU的执行权;
但是会放弃锁;
死锁产生的条件以及解决:
产生死锁必须同时满足以下四个条件,只要其中任一条件不成立,死锁就不会发生.通常破坏循环等待是最有效的方法。
互斥条件:一个资源每次只能被一个进程使用。
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放
不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
死锁代码示例:
/**
* 死锁测试
* A 和 B 不能同时获得筷子和勺子
*/
public class DeadThread {
A a = new A();//可以看做是共有的资源.
B b = new B();
public DeadThread() {
a.start();
b.start();
}
public static void main(String[] args) {
new DeadThread();
}
//线程A
class A extends Thread {
@Override
public void run() {
getSZ();
}
synchronized public void getSZ() {
System.out.println("我有勺子,我想要筷子");
try {
Thread.sleep(1000);
b.getKZ();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//线程B
class B extends Thread {
@Override
public void run() {
getKZ();
}
public synchronized void getKZ() {
System.out.println("我有筷子,我想要勺子");
try {
Thread.sleep(1000);
a.getSZ();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
了解更多多线程