public class Test {
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start();
MyThread t2 = new MyThread();
t2.start();
}
}
class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 50; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
}
}
}
}
比较创建线程的两种方式
public class Test {
public static void main(String[] args) {
MyThread m1 = new MyThread();
Runnable target;
Thread t1 = new Thread(m1);
t1.setName("线程一");
t1.start();
}
}
class MyThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 50; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
}
}
}
}
如何理解实现Callable接口的方式创建多线程比实现Runnable接口创建多线程方式强大?
public class Test {
public static void main(String[] args) {
// 1. 创建实现类的对象
NumThread numThread = new NumThread();
// 2. 将1中的对象传递到FutureTask构造器中
FutureTask futureTask = new FutureTask(numThread);
// 3. 创建Thread对象,调用start()方法
new Thread(futureTask).start();
// 4. 如果要获取返回值,使用下面方法
Object obj = null;
try {
obj = futureTask.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("返回值为:" + obj);
}
}
// 创建实现类
class NumThread implements Callable {
@Override
public Object call() throws Exception {
int sum = 0;
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
System.out.println(i);
sum += i;
}
}
return sum;
}
}
/**
* 线程需求一:
*/
class NumberThread implements Runnable{
@Override
public void run() {
for(int i = 0;i <= 100;i++){
if(i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
}
}
/**
* 线程需求二:
*/
class NumberThread1 implements Runnable{
@Override
public void run() {
for(int i = 0;i <= 100;i++){
if(i % 2 != 0){
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
}
}
public class ThreadPool {
public static void main(String[] args) {
//1. 提供指定线程数量的线程池
ThreadPoolExecutor service = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
//设置线程池的属性
/**
* service.setCorePoolSize(15);
* service.setKeepAliveTime();
*
* 2.执行指定的线程的操作。需要提供实现Runnable接口或Callable接口实现类的对象
* execute:适合适用于Runnable
* submit:Callable
*/
service.execute(new NumberThread());
service.execute(new NumberThread1());
//3.关闭连接池
service.shutdown();
}
线程的优先级:
如何获取和设置当前线程的优先级:
synchronized(同步监视器){
//需要被同步的代码
}
说明: 1.操作共享数据的代码,即为需要被同步的代码。 -->不能包含代码多了,也不能包含代码少了。
2.共享数据:多个线程共同操作的变量。比如:ticket就是共享数据。
3.同步监视器,俗称:锁。任何一个类的对象,都可以充当锁。
补充:在实现Runnable接口创建多线程的方式中,我们可以考虑使用this充当同步监视器。
如果操作共享数据的代码完整的声明在一个方法中,我们不妨将此方法声明同步的。
相同:二者都可以解决线程安全问题
不同:
synchronized机制在执行完相应的同步代码以后,自动的释放同步监视器
2.优先使用顺序:
class Window1 implements Runnable{ private int ticket = 100;
class Window1 implements Runnable{
private int ticket = 100;
@Override
public void run() {
while (true) {
synchronized (this) {
/*同步代码块*/
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + ticket);
ticket--;
} else {
break;
}
}
}
}
}
class Window1 implements Runnable{
private int ticket = 100;
@Override
public void run() {
while (true){
// 调用同步方法
go();
}
}
// 同步方法
private synchronized void go(){
if(ticket > 0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + ticket);
ticket--;
}
}
}
class Window1 extends Thread{
private static int ticket = 100;
private static Object obj = new Object();
@Override
public void run() {
while(true){
synchronized (obj){
if(ticket > 0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName() + ":卖票,票号为:" + ticket);
ticket--;
}else{
break;
}
}
}
}
}
class Window1 extends Thread{
private static int ticket = 100;
/**
* 实例化lock
* */
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true){
// 加锁
lock.lock();
if (ticket > 0 ) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + ticket);
ticket--;
}else{
break;
}
// 解锁
lock.unlock();
}
}
}
线程通信的例子:使用两个线程打印 1-100。线程1, 线程2 交替打印
涉及到的三个方法:
说明:
sleep() 和 wait()的异同?